Começar

Primeiros passos

Do zero à primeira factura emitida por API, passo a passo, com pedidos e respostas reais.

Este guia leva-o do zero até uma factura/recibo emitida por API. Os pedidos e as respostas abaixo são reais, capturados de uma empresa de demonstração («Mutamba Comercial»).

#1. Crie uma chave

  1. 1
    Crie um perfil só para a integração

    Em Definições › Perfis e permissões, crie um perfil (por exemplo «Integração – loja online») com as permissões estritamente necessárias. O guia Permissões e alcance lista as de cada cenário.

  2. 2
    Crie a chave

    Em Definições › Chaves de API › Nova chave, dê-lhe um nome, escolha o perfil e, se quiser, prenda-a a um estabelecimento, defina uma data de validade e os endereços de rede de onde pode ser usada.

  3. 3
    Copie o segredo

    O segredo mostra-se uma única vez. O sistema só guarda uma impressão dele: se o perder, crie uma chave nova e revogue a antiga.

#2. Teste a ligação

Peça os dados da empresa. A chave segue no cabeçalho X-Api-Key:

Os dados da própria empresa

Pedido
curl 'https://<endereço-da-API>/api/empresa' \
  -H 'X-Api-Key: assw_v1_<chave>'
Pedido
const resposta = await fetch('https://<endereço-da-API>/api/empresa', {
  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/empresa',
    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/empresa");
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

{
  "nome": "Mutamba Comercial, Lda.",
  "slug": "mutamba-comercial",
  "email": "geral@mutambacomercial.co.ao",
  "numeroContribuinte": "5417000987",
  "endereco": "Rua da Missão, n.º 45, Luanda",
  "municipioId": "c8a4df25-a9c1-d51f-9223-367545fbcb49",
  "regimeFiscalId": "01a0ee03-0fe7-7d63-aca7-e189893867d9",
  "informacaoFactura": "Mercadoria entregue e conferida pelo cliente. Mutamba Comercial, Lda. — comércio a retalho e a grosso.",
  "contasBancarias": [
    {
      "banco": "Banco BAI",
      "numeroConta": "0040.0000.1234.5678.1013.1",
      "iban": "AO06.0040.0000.1234.5678.1013.1"
    },
    {
      "banco": "Banco BFA",
      "numeroConta": "0006.0000.9876.5432.1011.2",
      "iban": "AO06.0006.0000.9876.5432.1011.2"
    }
  ],
  "telefone": "+244 923 456 789",
  "website": "www.mutamba-demo.example",
  "temLogotipo": false,
  "observacao": null,
  "temChaveAssinatura": true,
  "numeroCertificadoAgt": "0001",
  "versaoChaveAssinatura": "1",
  "dadosFiscaisBloqueados": true
}

#3. Obtenha os identificadores

Para emitir um documento precisa de identificadores: o tipo de documento, o método de pagamento, o estabelecimento, o armazém, o cliente e o artigo. Obtém-nos com pedidos de leitura e pode guardá-los: quase nunca mudam.

O tipo de documento («FR» = factura/recibo)

Pedido
curl 'https://<endereço-da-API>/api/documentos/tipos' \
  -H 'X-Api-Key: assw_v1_<chave>'
Pedido
const resposta = await fetch('https://<endereço-da-API>/api/documentos/tipos', {
  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/documentos/tipos',
    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/documentos/tipos");
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": "2a6a1e94-6e0d-4b8e-9f42-8f6a2f0c7b41",
    "descricao": "Factura",
    "categoria": "Financeiros",
    "naturezaDocumento": "AReceberDebita",
    "movimentaEstoque": true,
    "tipoMovimentoDocumento": "Saida",
    "contaCorrente": true,
    "siglaDocumento": "FT",
    "tipoLancamentoCliente": "Debito",
    "categoriaSaft": "SalesInvoices",
    "requerAssinatura": true
  },
  {
    "id": "8c1b5e2a-3f7d-4a6e-8b0a-1d5c7e9f3a63",
    "descricao": "Factura Pro-Forma",
    "categoria": "Cotacao",
    "naturezaDocumento": "SemInfluencia",
    "movimentaEstoque": false,
    "tipoMovimentoDocumento": "Nenhum",
    "contaCorrente": false,
    "siglaDocumento": "PP",
    "tipoLancamentoCliente": null,
    "categoriaSaft": "WorkingDocuments",
    "requerAssinatura": true
  },
  {
    "id": "6d3f9c9b-6d0a-4e4d-9a9a-2c9f8b1e4d52",
    "descricao": "Factura/Recibo",
    "categoria": "Financeiros",
    "naturezaDocumento": "AReceberDebita",
    "movimentaEstoque": true,
    "tipoMovimentoDocumento": "Saida",
    "contaCorrente": false,
    "siglaDocumento": "FR",
    "tipoLancamentoCliente": null,
    "categoriaSaft": "SalesInvoices",
    "requerAssinatura": true
  },
  {
    "id": "e5c9f6a4-7d86-4b2a-9f43-9a5d1c6e8b32",
    "descricao": "Guia de Devolução",
    "categoria": "Transporte",
    "naturezaDocumento": "SemInfluencia",
    "movimentaEstoque": true,
    "tipoMovimentoDocumento": "EntradaDevolucao",
    "contaCorrente": false,
    "siglaDocumento": "GD",
    "tipoLancamentoCliente": null,
    "categoriaSaft": "MovementOfGoods",
    "requerAssinatura": true
  },
  {
    "id": "c1a7d3e2-5b64-4f08-9d21-7e3b9a4c6f10",
    "descricao": "Guia de Remessa",
    "categoria": "Transporte",
    "naturezaDocumento": "SemInfluencia",
    "movimentaEstoque": true,
    "tipoMovimentoDocumento": "Saida",
  …

O método de pagamento

Pedido
curl 'https://<endereço-da-API>/api/metodos-pagamento' \
  -H 'X-Api-Key: assw_v1_<chave>'
Pedido
const resposta = await fetch('https://<endereço-da-API>/api/metodos-pagamento', {
  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/metodos-pagamento',
    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/metodos-pagamento");
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": "eac54012-cede-4eb6-b2f5-f23459bc9ac2",
    "descricao": "Multicaixa",
    "tipoLancamento": "Credito",
    "pedirComprovativo": true,
    "aceitaContaCorrente": false,
    "activo": true
  },
  {
    "id": "9dde532b-0092-4a68-b2dc-18649f0c97c4",
    "descricao": "Numerário",
    "tipoLancamento": "Credito",
    "pedirComprovativo": false,
    "aceitaContaCorrente": false,
    "activo": true
  },
  {
    "id": "1fe6ebd7-682b-4297-a89f-876506fe18e4",
    "descricao": "Transferência Bancária",
    "tipoLancamento": "Credito",
    "pedirComprovativo": true,
    "aceitaContaCorrente": false,
    "activo": true
  }
]

Os estabelecimentos

Pedido
curl 'https://<endereço-da-API>/api/lojas' \
  -H 'X-Api-Key: assw_v1_<chave>'
Pedido
const resposta = await fetch('https://<endereço-da-API>/api/lojas', {
  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/lojas',
    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/lojas");
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": "01a12201-f4d4-7c07-86b7-e5b24035993e",
    "nome": "Loja Central",
    "codigo": "LC",
    "endereco": "Rua da Missão, n.º 45, Luanda",
    "limiteAlertaSaldoGaveta": null,
    "toleranciaQuebraFechoCaixa": 0,
    "fechamentoCegoActivo": true,
    "municipioId": null
  },
  {
    "id": "01a12201-f4d4-7da7-a880-4239624940d5",
    "nome": "Loja de Viana",
    "codigo": "LV",
    "endereco": "Estrada de Catete, Viana",
    "limiteAlertaSaldoGaveta": null,
    "toleranciaQuebraFechoCaixa": 0,
    "fechamentoCegoActivo": true,
    "municipioId": null
  }
]

O armazém do estabelecimento

Pedido
curl 'https://<endereço-da-API>/api/estoque/armazens?tamanho=5' \
  -H 'X-Api-Key: assw_v1_<chave>'
Pedido
const resposta = await fetch('https://<endereço-da-API>/api/estoque/armazens?tamanho=5', {
  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/estoque/armazens?tamanho=5',
    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/estoque/armazens?tamanho=5");
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-f4d4-7215-996c-6e230d2c67f6",
      "descricao": "Armazém Principal",
      "localizacao": "Loja de Viana",
      "predefinido": true,
      "lojaId": "01a12201-f4d4-7da7-a880-4239624940d5",
      "lojaNome": "Loja de Viana"
    },
    {
      "id": "01a12201-f4d4-78a0-8dde-1efc41b94776",
      "descricao": "Armazém Principal",
      "localizacao": "Loja Central",
      "predefinido": true,
      "lojaId": "01a12201-f4d4-7c07-86b7-e5b24035993e",
      "lojaNome": "Loja Central"
    },
    {
      "id": "01a12201-fc2b-7c7c-801f-ebf0cc7fbebc",
      "descricao": "Armazém de Reserva",
      "localizacao": "Loja Central — traseiras",
      "predefinido": false,
      "lojaId": "01a12201-f4d4-7c07-86b7-e5b24035993e",
      "lojaNome": "Loja Central"
    }
  ],
  "proximoCursor": null
}

O artigo, com o preço, o imposto e o saldo no armazém

Pedido
curl 'https://<endereço-da-API>/api/produtos/pesquisa-venda?filtro=arroz&armazemId=01a12201-f4d4-78a0-8dde-1efc41b94776&tamanho=1' \
  -H 'X-Api-Key: assw_v1_<chave>'
Pedido
const resposta = await fetch('https://<endereço-da-API>/api/produtos/pesquisa-venda?filtro=arroz&armazemId=01a12201-f4d4-78a0-8dde-1efc41b94776&tamanho=1', {
  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/produtos/pesquisa-venda?filtro=arroz&armazemId=01a12201-f4d4-78a0-8dde-1efc41b94776&tamanho=1',
    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/produtos/pesquisa-venda?filtro=arroz&armazemId=01a12201-f4d4-78a0-8dde-1efc41b94776&tamanho=1");
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": "01a12201-fa97-7f9b-8eec-2f731b91a53b",
    "codigoInterno": "MC0001",
    "codigoBarra": "560000100137",
    "nome": "Arroz agulha 5 kg",
    "tipoProduto": "Produto",
    "unidadeDescricao": "Unidade",
    "pvp1": 6500,
    "pvp2": 6250,
    "pvp3": 6000,
    "pvp4": 5750,
    "impostoId": "962b1189-25af-4864-bd7b-495a30abbc65",
    "impostoPercentual": 14,
    "motivoIsencaoIvaId": null,
    "taxaRetencaoId": null,
    "estocavel": true,
    "composto": false,
    "activo": true,
    "saldoNoArmazem": 536,
    "controlarValidade": false,
    "categoriaId": "01a12201-f8f9-7742-80ac-50e40368af4d",
    "unidadesVenda": [],
    "grupoVariacaoId": null,
    "grupoVariacaoNome": null,
    "variacao": null
  }
]

#4. Crie o cliente

Se o cliente ainda não existe, crie-o. Note o cabeçalho Idempotency-Key: gere um valor novo (um GUID) para cada intenção e guarde-o até ter a resposta.

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"
}

#5. Emita a factura/recibo

O pedido leva o tipo, o cliente, o estabelecimento, o armazém, as linhas e os pagamentos. O imposto não se envia: o servidor deriva-o do artigo. O pagamento tem de somar exactamente o total (aqui, 2 × 6 500 Kz + 14 % de IVA = 14 820 Kz).

Emitir uma Factura/Recibo paga em numerário

Pedido
curl -X POST 'https://<endereço-da-API>/api/documentos' \
  -H 'Idempotency-Key: 4756676e-a135-4e46-9ce8-3a5502ea85f0' \
  -H 'X-Api-Key: assw_v1_<chave>' \
  -H 'Content-Type: application/json' \
  -d '{
  "tipoDocumentoId": "6d3f9c9b-6d0a-4e4d-9a9a-2c9f8b1e4d52",
  "clienteId": "01a12f69-98f8-7688-85b9-8d829c101c8b",
  "armazemId": "01a12201-f4d4-78a0-8dde-1efc41b94776",
  "lojaId": "01a12201-f4d4-7c07-86b7-e5b24035993e",
  "observacao": "Pedido #4821 da loja online",
  "itens": [
    {
      "produtoId": "01a12201-fa97-7f9b-8eec-2f731b91a53b",
      "quantidade": 2,
      "precoUnitario": 6500,
      "descontoPercentual": 0
    }
  ],
  "pagamentos": [
    {
      "metodoPagamentoId": "9dde532b-0092-4a68-b2dc-18649f0c97c4",
      "valor": 14820
    }
  ]
}'
Pedido
const resposta = await fetch('https://<endereço-da-API>/api/documentos', {
  method: 'POST',
  headers: {
    "Idempotency-Key": "4756676e-a135-4e46-9ce8-3a5502ea85f0",
    "X-Api-Key": "assw_v1_<chave>",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "tipoDocumentoId": "6d3f9c9b-6d0a-4e4d-9a9a-2c9f8b1e4d52",
    "clienteId": "01a12f69-98f8-7688-85b9-8d829c101c8b",
    "armazemId": "01a12201-f4d4-78a0-8dde-1efc41b94776",
    "lojaId": "01a12201-f4d4-7c07-86b7-e5b24035993e",
    "observacao": "Pedido #4821 da loja online",
    "itens": [
      {
        "produtoId": "01a12201-fa97-7f9b-8eec-2f731b91a53b",
        "quantidade": 2,
        "precoUnitario": 6500,
        "descontoPercentual": 0
      }
    ],
    "pagamentos": [
      {
        "metodoPagamentoId": "9dde532b-0092-4a68-b2dc-18649f0c97c4",
        "valor": 14820
      }
    ]
  }),
})
const dados = await resposta.json()
Pedido
import requests

resposta = requests.post(
    'https://<endereço-da-API>/api/documentos',
    headers={
        'Idempotency-Key': '4756676e-a135-4e46-9ce8-3a5502ea85f0',
        'X-Api-Key': 'assw_v1_<chave>',
        'Content-Type': 'application/json'
    },
    json={
        'tipoDocumentoId': '6d3f9c9b-6d0a-4e4d-9a9a-2c9f8b1e4d52',
        'clienteId': '01a12f69-98f8-7688-85b9-8d829c101c8b',
        'armazemId': '01a12201-f4d4-78a0-8dde-1efc41b94776',
        'lojaId': '01a12201-f4d4-7c07-86b7-e5b24035993e',
        'observacao': 'Pedido #4821 da loja online',
        'itens': [
            {
                'produtoId': '01a12201-fa97-7f9b-8eec-2f731b91a53b',
                'quantidade': 2,
                'precoUnitario': 6500,
                'descontoPercentual': 0
            }
        ],
        'pagamentos': [
            {
                'metodoPagamentoId': '9dde532b-0092-4a68-b2dc-18649f0c97c4',
                'valor': 14820
            }
        ]
    },
)
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/documentos");
pedido.Headers.Add("Idempotency-Key", "4756676e-a135-4e46-9ce8-3a5502ea85f0");
pedido.Headers.Add("X-Api-Key", "assw_v1_<chave>");
pedido.Content = new StringContent("""
{
  "tipoDocumentoId": "6d3f9c9b-6d0a-4e4d-9a9a-2c9f8b1e4d52",
  "clienteId": "01a12f69-98f8-7688-85b9-8d829c101c8b",
  "armazemId": "01a12201-f4d4-78a0-8dde-1efc41b94776",
  "lojaId": "01a12201-f4d4-7c07-86b7-e5b24035993e",
  "observacao": "Pedido #4821 da loja online",
  "itens": [
    {
      "produtoId": "01a12201-fa97-7f9b-8eec-2f731b91a53b",
      "quantidade": 2,
      "precoUnitario": 6500,
      "descontoPercentual": 0
    }
  ],
  "pagamentos": [
    {
      "metodoPagamentoId": "9dde532b-0092-4a68-b2dc-18649f0c97c4",
      "valor": 14820
    }
  ]
}
""", 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/documentos/01a12f69-9a59-714a-9d67-10d65ba202cf

{
  "id": "01a12f69-9a59-714a-9d67-10d65ba202cf"
}

#6. Consulte o documento

Consultar o documento emitido

Pedido
curl 'https://<endereço-da-API>/api/documentos/01a12f69-9a59-714a-9d67-10d65ba202cf' \
  -H 'X-Api-Key: assw_v1_<chave>'
Pedido
const resposta = await fetch('https://<endereço-da-API>/api/documentos/01a12f69-9a59-714a-9d67-10d65ba202cf', {
  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/documentos/01a12f69-9a59-714a-9d67-10d65ba202cf',
    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/documentos/01a12f69-9a59-714a-9d67-10d65ba202cf");
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-9a59-714a-9d67-10d65ba202cf",
  "tipoDocumentoId": "6d3f9c9b-6d0a-4e4d-9a9a-2c9f8b1e4d52",
  "numero": "FR LC2026/29",
  "data": "2026-10-12T09:20:12.399987Z",
  "clienteId": "01a12f69-98f8-7688-85b9-8d829c101c8b",
  "clienteNome": "Mercearia Cazenga Nova",
  "caixaId": null,
  "armazemId": "01a12201-f4d4-78a0-8dde-1efc41b94776",
  "referenciaExternaId": null,
  "estado": "Novo",
  "motivoAnulacao": null,
  "observacao": "Pedido #4821 da loja online",
  "hash": "a17i27DU2J53A1VG+U4XkfLa8muGqAxJaKe1TxIb9CmC06j9AipBsYPafR0N/1ifG7G9tPy/ScVnEVpENAp3D+2a2lOcL7z3VGd++57xznZRepA+uJMEjEy9NIpFMK1VWHXmca/4FVTzG2leahl18S/mgKYN50LKdRz1gK39oCA=",
  "hashControlo": "a5kx",
  "versaoChavePrivada": "1",
  "dataHoraAssinatura": "2026-10-12T09:20:12.410197Z",
  "subtotal": 13000,
  "valorImposto": 1820,
  "totalValorRetencao": 0,
  "valorLiquidado": 0,
  "valorCreditado": 0,
  "vendedorOriginadorId": null,
  "vendedorFaturadorId": null,
  "outrosEncargos": 0,
  "referenciaCliente": null,
  "montantePago": 14820,
  "totalDesconto": 0,
  "operadorNome": null,
  "dataVencimento": null,
  "registadoOfflineEmUtc": null,
  "chaveApiId": "01a12f69-9867-79c2-ad0c-811c6899737a",
  "totalGeral": 14820,
  "totalRecebido": 14820,
  "totalDocumento": 14820,
  "valorPendente": 0,
  "totalGeralPorExtenso": "catorze mil oitocentos e vinte kwanzas",
  "itens": [
    {
      "id": "01a12f69-9a75-71ff-8c4f-163cce92fd02",
      "produtoId": "01a12201-fa97-7f9b-8eec-2f731b91a53b",
      "loteId": null,
      "descricao": "Arroz agulha 5 kg",
      "precoUnitario": 6500,
      "quantidade": 2,
      "descontoPercentual": 0,
      "descontoFinanceiroPercentual": 0,
      "impostoPercentual": 14,
      "taxaRetencaoPercentual": 0,
      "referenciaItemOrigemId": null,
      "creditadaEmDocumentoId": null,
      "motivoAnulacaoItem": null,
      "descontoPromocao": 0,
      "promocaoId": null,
      "promocaoNome": null,
      "oferta": false,
      "precoTotal": 13000,
      "valorDesconto": 0,
      "subtotal": 13000,
      "valorImposto": 1820,
  …

O numero («FR LC2026/25») é atribuído pelo servidor, sequencial e sem lacunas. hash e hashControlo são a assinatura digital. chaveApiId é a chave que emitiu o documento.

#7. Repita o pedido, em segurança

Se a ligação cair antes de receber a resposta, repita exactamente o mesmo pedido com a mesma Idempotency-Key. O servidor devolve o documento já emitido (com Idempotency-Replayed: true) em vez de emitir outro:

Repetir o pedido (a rede falhou antes da resposta): o mesmo documento, sem emitir outro

Pedido
curl -X POST 'https://<endereço-da-API>/api/documentos' \
  -H 'Idempotency-Key: 4756676e-a135-4e46-9ce8-3a5502ea85f0' \
  -H 'X-Api-Key: assw_v1_<chave>' \
  -H 'Content-Type: application/json' \
  -d '{
  "tipoDocumentoId": "6d3f9c9b-6d0a-4e4d-9a9a-2c9f8b1e4d52",
  "clienteId": "01a12f69-98f8-7688-85b9-8d829c101c8b",
  "armazemId": "01a12201-f4d4-78a0-8dde-1efc41b94776",
  "lojaId": "01a12201-f4d4-7c07-86b7-e5b24035993e",
  "observacao": "Pedido #4821 da loja online",
  "itens": [
    {
      "produtoId": "01a12201-fa97-7f9b-8eec-2f731b91a53b",
      "quantidade": 2,
      "precoUnitario": 6500,
      "descontoPercentual": 0
    }
  ],
  "pagamentos": [
    {
      "metodoPagamentoId": "9dde532b-0092-4a68-b2dc-18649f0c97c4",
      "valor": 14820
    }
  ]
}'
Pedido
const resposta = await fetch('https://<endereço-da-API>/api/documentos', {
  method: 'POST',
  headers: {
    "Idempotency-Key": "4756676e-a135-4e46-9ce8-3a5502ea85f0",
    "X-Api-Key": "assw_v1_<chave>",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "tipoDocumentoId": "6d3f9c9b-6d0a-4e4d-9a9a-2c9f8b1e4d52",
    "clienteId": "01a12f69-98f8-7688-85b9-8d829c101c8b",
    "armazemId": "01a12201-f4d4-78a0-8dde-1efc41b94776",
    "lojaId": "01a12201-f4d4-7c07-86b7-e5b24035993e",
    "observacao": "Pedido #4821 da loja online",
    "itens": [
      {
        "produtoId": "01a12201-fa97-7f9b-8eec-2f731b91a53b",
        "quantidade": 2,
        "precoUnitario": 6500,
        "descontoPercentual": 0
      }
    ],
    "pagamentos": [
      {
        "metodoPagamentoId": "9dde532b-0092-4a68-b2dc-18649f0c97c4",
        "valor": 14820
      }
    ]
  }),
})
const dados = await resposta.json()
Pedido
import requests

resposta = requests.post(
    'https://<endereço-da-API>/api/documentos',
    headers={
        'Idempotency-Key': '4756676e-a135-4e46-9ce8-3a5502ea85f0',
        'X-Api-Key': 'assw_v1_<chave>',
        'Content-Type': 'application/json'
    },
    json={
        'tipoDocumentoId': '6d3f9c9b-6d0a-4e4d-9a9a-2c9f8b1e4d52',
        'clienteId': '01a12f69-98f8-7688-85b9-8d829c101c8b',
        'armazemId': '01a12201-f4d4-78a0-8dde-1efc41b94776',
        'lojaId': '01a12201-f4d4-7c07-86b7-e5b24035993e',
        'observacao': 'Pedido #4821 da loja online',
        'itens': [
            {
                'produtoId': '01a12201-fa97-7f9b-8eec-2f731b91a53b',
                'quantidade': 2,
                'precoUnitario': 6500,
                'descontoPercentual': 0
            }
        ],
        'pagamentos': [
            {
                'metodoPagamentoId': '9dde532b-0092-4a68-b2dc-18649f0c97c4',
                'valor': 14820
            }
        ]
    },
)
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/documentos");
pedido.Headers.Add("Idempotency-Key", "4756676e-a135-4e46-9ce8-3a5502ea85f0");
pedido.Headers.Add("X-Api-Key", "assw_v1_<chave>");
pedido.Content = new StringContent("""
{
  "tipoDocumentoId": "6d3f9c9b-6d0a-4e4d-9a9a-2c9f8b1e4d52",
  "clienteId": "01a12f69-98f8-7688-85b9-8d829c101c8b",
  "armazemId": "01a12201-f4d4-78a0-8dde-1efc41b94776",
  "lojaId": "01a12201-f4d4-7c07-86b7-e5b24035993e",
  "observacao": "Pedido #4821 da loja online",
  "itens": [
    {
      "produtoId": "01a12201-fa97-7f9b-8eec-2f731b91a53b",
      "quantidade": 2,
      "precoUnitario": 6500,
      "descontoPercentual": 0
    }
  ],
  "pagamentos": [
    {
      "metodoPagamentoId": "9dde532b-0092-4a68-b2dc-18649f0c97c4",
      "valor": 14820
    }
  ]
}
""", 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
idempotency-replayed: true
location: /api/documentos/01a12f69-9a59-714a-9d67-10d65ba202cf

{
  "id": "01a12f69-9a59-714a-9d67-10d65ba202cf"
}

#E agora?