zComercial API api.zcomercial.com · facetas v1 · siga · v2  —  API v3 →
Referência da API

zComercial · API de integração

Emita facturas, recibos e notas de crédito a partir do seu sistema (ERP, loja online, software de gestão escolar…). Toda a emissão é certificada AGT: a assinatura SAF-T e, quando a empresa aderiu à Facturação Electrónica, a comunicação à AGT são feitas pelo zComercial. O integrador só envia o documento.

A API está em https://api.zcomercial.com e tem três facetas, que partilham a mesma chave e os mesmos documentos:

FacetaPara quê
/v1/Integração geral. Emissão com resposta imediata na maioria dos casos (ver Emitir factura). Recomendada para novas integrações.
/siga/Emissão síncrona pontual, um documento de cada vez. É a única com nota de crédito. Usada pelo SIGA e útil a qualquer integrador.
/v2/Assíncrona (fila + consulta de estado). Mantida por compatibilidade — ver Faceta v2.
Empresas já migradas para a nova geração da plataforma usam a API v3 (outro endereço, com nota de débito e cancelamento). Em caso de dúvida sobre qual usar, contacte o suporte zComercial.
Base URL
https://api.zcomercial.com
Fluxo típico
1. POST /v1/invoice/create      → invoice.id
2. POST /v1/invoice/pdf         → pdf.invoice_url
3. POST /v1/invoice/payment     → receipt (se FT)
4. POST /siga/invoice/creditnote → note (anulação)
Formato
Content-Type: application/json
Histórico

O que mudou

Alterações com efeito para quem integra, da mais recente para a mais antiga.

Setembro de 2026

  • Nota de crédito por API — novo POST /siga/invoice/creditnote, que anula integralmente uma factura. É idempotente: repetir o pedido devolve a mesma nota. Ver detalhes.
  • Cliente com campos em falta — deixou de falhar. Antes, um pedido sem postal_code, city, country, website, fax, mobile ou short_name podia devolver uma página de erro ou sair em nome de «Consumidor final». Agora só são obrigatórios o fiscal_id e o address.
  • Talão de 80 mm (doc: "invoicemini") — novo desenho, com o número AGT e o QR de validação quando a empresa está na Facturação Electrónica. A altura do papel ajusta-se ao conteúdo.
  • Factura-Recibo na faceta siga — type: "FR" passou a ser aceite, com payment_mechanism obrigatório.
  • Facturação Electrónica na faceta siga — nas empresas aderentes, o documento recebe número AGT e é comunicado à AGT automaticamente.

Agosto de 2026

  • /v1/invoice/create espera agora até 10 segundos (antes 5) pelo documento. A maioria dos pedidos passou a receber 200 com a factura em vez de 202.

Primeiro semestre de 2026

  • /v1/invoice/create passou a usar a fila de emissão. Devolve 200 com a factura, ou 202 com um process_id para consultar depois. Ver Emitir factura.
  • Pedidos duplicados — o mesmo corpo enviado duas vezes em 24 horas é recusado com 409 e o process_id do original. Protege contra emissões em duplicado quando o integrador repete um pedido.
  • Validação — erros de dados passaram a devolver 400 na faceta v1 (antes 404). Descontos e retenções fora de 0–100% e valores negativos são recusados.
  • Faceta v2 assíncrona.
Resposta 202 (v1)
{
  "status": true,
  "message": "A fatura está a demorar mais do que o esperado, mas foi enfileirada.",
  "process_id": 91823,
  "status_url": "https://api.zcomercial.com/v2/Invoice/invoicestatus/91823"
}
Resposta 409 (duplicado)409
{
  "status": false,
  "message": "Payload duplicado. Esta fatura já foi submetida recentemente.",
  "process_id": 91823,
  "status_url": "https://api.zcomercial.com/v2/Invoice/invoicestatus/91823"
}
Segurança

Autenticação

Cada empresa tem uma chave de API. Envie-a no cabeçalho Authorization de todos os pedidos, sem prefixo (sem Bearer).

Peça a chave ao suporte zComercial. Guarde-a como uma palavra-passe: quem a tiver emite documentos fiscais em nome da empresa.

  • Chave em falta ou inválida → 404 com o corpo "Not Found" (não 401).
  • Subscrição expirada → 404 com "O seu periodo de subscrição terminou".
  • A consulta de estado e a faceta v2 lêem a chave do cabeçalho Authorization2. Envie os dois cabeçalhos com a mesma chave e fica coberto em todos os endpoints.
Cabeçalhos
Authorization: <chave-da-empresa>
Authorization2: <chave-da-empresa>
Content-Type: application/json
curl
curl https://api.zcomercial.com/v1/invoice \
  -H "Authorization: A1B2C3D4E5" \
  -H "Authorization2: A1B2C3D4E5"
Chave inválida404
"Not Found"
Antes de começar

Conceitos

Tipos de documento

CódigoDocumentoComo se emite
FTFactura (paga depois)invoice.type = "FT"
FRFactura-Recibo (paga no acto)invoice.type = "FR"
PPFactura Proforma (não fiscal)invoice.type = "PP"
RCRecibo de uma FT/invoice/payment
NCNota de Crédito (anulação)/siga/invoice/creditnote

A referência id

Cada documento emitido devolve um id opaco (ex.: 66f0c1a2b3c4d). Guarde-o. É com ele que regista o pagamento, pede o PDF ou emite a nota de crédito. O número impresso (sequence_number, ex.: FT 2026/104) não serve de referência.

Cliente

O cliente identifica-se pelo NIF (client.fiscal_id). Se o NIF ainda não existe na empresa, o zComercial confirma-o na AGT e usa o nome oficial devolvido; o name enviado é ignorado. Sem o objecto client, o documento sai em nome de Consumidor final.

Artigos

Os artigos identificam-se pelo nome. Um nome novo cria o artigo com o preço, o tipo e a descrição enviados. Se o artigo já existe, os totais do documento são calculados com o preço que está registado no artigo. Envie sempre o mesmo preço que está registado, ou use um nome diferente para um preço diferente. Artigos do tipo P (produto) descontam stock.

Série, imposto, moeda e vencimento

Vêm da configuração da empresa no zComercial: série activa, imposto activo (aplicado a todas as linhas), moeda principal e prazo de vencimento. Na faceta v1 pode escolher a série com invoice.serie.

Referência devolvida na emissão
{
  "invoice": {
    "id": "66f0c1a2b3c4d",        ← guardar
    "sequence_number": "FT 2026/104",
    "status": "Final",
    ...
  }
}
Estados de um documento
Final      emitido, por pagar (FT) ou proforma
Pago       FR, ou FT paga pelos recibos
Cancelado  anulado
Documentos

Emitir factura (v1)

POST/v1/invoice/create

Emite uma FT, FR ou PP. O pedido entra na fila de emissão e a API espera até 10 segundos pelo resultado:

  • 200 — o documento foi emitido; o corpo é o objecto invoice. Confirme que não veio "status": false (ver abaixo).
  • 202 — ainda em processamento. Guarde o process_id e consulte o estado. Não reenvie o pedido: seria recusado como duplicado (409) ou, depois de 24 horas, emitido duas vezes.
  • 400 — dados inválidos, ou a emissão falhou no processamento.
  • 409 — o mesmo corpo já foi enviado nas últimas 24 horas. Use o process_id devolvido para obter o documento original.
Uma regra fiscal pode impedir a emissão já dentro da fila (por exemplo, uma data anterior à do último documento finalizado da mesma série). Nesse caso a resposta 200 traz {"status": false, "message": "…"} em vez do objecto invoice. Verifique sempre se existe invoice.id.

Campos: ver Esquemas. Na faceta v1, payment_mechanism é opcional para FR (por omissão, OU).

Pedido
curl -X POST https://api.zcomercial.com/v1/invoice/create \
  -H "Authorization: A1B2C3D4E5" \
  -H "Content-Type: application/json" \
  -d '{
  "invoice": {
    "type": "FT",
    "date": "2026-09-30",
    "observations": "Encomenda #4471",
    "reference": "PO-4471",
    "client": {
      "fiscal_id": "5417222925",
      "address": "Rua Direita do Zango, Luanda",
      "email": "compras@cliente.co.ao"
    },
    "items": [
      { "name": "Consultoria", "description": "Setembro",
        "unit_price": 50000, "quantity": 2, "discount": 0, "type": "S" },
      { "name": "Toner HP 85A", "description": "Toner HP 85A",
        "unit_price": 18000, "quantity": 1, "discount": 0, "type": "P" }
    ]
  }
}'
Resposta200
{
  "invoice": {
    "id": "66f0c1a2b3c4d",
    "sequence_number": "FT 2026/104",
    "status": "Final",
    "archived": "0",
    "type": "Factura",
    "date": "2026-09-30",
    "time": "14:57",
    "saft_hash": "aB3f",
    "tax_exemption": "",
    "due_date": "2026-10-30",
    "reference": "PO-4471",
    "observations": "Encomenda #4471",
    "retention": "0",
    "currency": "AOA",
    "valor": "134520",
    "client": { "id": "812", "name": "GLOBAL CATERING, LDA", "fiscal_id": "5417222925" },
    "items": [ ... ],
    "mx_reference": { "entity": "", "value": "134520", "reference": "" }
  }
}
Emissão recusada na fila200
{
  "status": false,
  "message": "Erro, não pode finalizar um rascunho com data inferior a facturas finalizadas"
}
Documentos

Consultar estado

GET/v2/Invoice/invoicestatus/{process_id}

Para os pedidos que devolveram 202 (ou 409). É o endereço que vem em status_url. Este endpoint lê a chave do cabeçalho Authorization2.

Devolve o registo da fila. Os campos que interessam:

CampoSignificado
statusPENDING na fila · PROCESSING a emitir · DONE terminado · ERROR falhou
resultEm DONE: o JSON do documento, como texto — faça JSON.parse/json_decode. Pode ser {"status":false,…} se a emissão foi recusada. Em ERROR: a mensagem de erro.
processado_emQuando terminou.

Consulte com intervalo crescente (1 s, 2 s, 4 s…). Normalmente o documento está pronto em poucos segundos.

Pedido
curl https://api.zcomercial.com/v2/Invoice/invoicestatus/91823 \
  -H "Authorization2: A1B2C3D4E5"
Resposta200
{
  "id": "91823",
  "status": "DONE",
  "result": "{\"invoice\":{\"id\":\"66f0c1a2b3c4d\",\"sequence_number\":\"FT 2026/104\", ...}}",
  "created_at": "2026-09-30 14:57:02",
  "processado_em": "2026-09-30 14:57:09",
  ...
}
Documentos

Emitir factura (siga)

POST/siga/invoice/create

Mesmo corpo e mesma resposta da v1, com duas diferenças:

  • Síncrona: não passa pela fila — a resposta é sempre o documento emitido (200) ou um erro. Indicada para emissão pontual, um documento de cada vez.
  • FR exige payment_mechanism (ver Meios de pagamento). A série é sempre a activa da empresa (serie é ignorado).

Nesta faceta, os erros de validação devolvem 404 com {"status": false, "message": "…"}. Pedidos duplicados em 24 horas devolvem 409.

Pedido — Factura-Recibo
{
  "invoice": {
    "type": "FR",
    "date": "2026-09-30",
    "payment_mechanism": "MB",
    "client": { "fiscal_id": "5417222925", "address": "Luanda" },
    "items": [
      { "name": "Propina Outubro", "description": "Propina Outubro",
        "unit_price": 35000, "quantity": 1, "discount": 0, "type": "S" }
    ]
  }
}
FR sem meio de pagamento400
{
  "status": false,
  "message": "Erro, payment_mechanism é obrigatório para Factura Recibo (FR)"
}
Documentos

Registar pagamento

POST/v1/invoice/payment
POST/siga/invoice/payment

Emite um Recibo (RC) sobre uma factura FT em estado Final. Síncrono nas duas facetas.

  • Pagamentos parciais são aceites. Quando a soma dos recibos atinge o valor em dívida, a factura passa a Pago.
  • Um valor acima do que falta pagar é recusado.
  • FR não aceita recibo (já está paga); PP também não.

Para obter o PDF do recibo, use /invoice/pdf com doc: "receipt" e o receipt.id.

Pedido
{
  "payment": {
    "invoice": "66f0c1a2b3c4d",
    "amount": 50000,
    "payment_date": "2026-10-05",
    "payment_mechanism": "TB",
    "note": "1.ª prestação"
  }
}
Resposta200
{
  "receipt": {
    "id": "66f2a9e01d7b3",
    "sequence_number": "RC 2026/57",
    "status": "Pago",
    "type": "Recibo",
    "date": "2026-10-05",
    "valor": "50000",
    "custumer": { ... },
    "items": [ ... ]
  }
}
Valor acima da dívida404
{
  "status": false,
  "message": "Erro ao tentar alterar os dados, pagamento superior ao valor da factura"
}
Documentos · novo

Nota de crédito

POST/siga/invoice/creditnote

Emite uma Nota de Crédito de anulação integral de uma factura (FT ou FR). Serve para qualquer factura da empresa, emitida por qualquer faceta.

  • Não se enviam linhas: a nota copia a série, o cliente, as linhas e os valores da factura de origem. O número sai como NC <série>/<n>.
  • Idempotente: se a factura já tiver uma nota de crédito que a anula, a API devolve essa nota com "already_existed": true em vez de criar outra. Pode repetir o pedido com segurança (por exemplo, depois de um timeout).
  • Os produtos (tipo P) voltam ao stock.
  • Na Facturação Electrónica, a nota é comunicada à AGT como a factura.

Quando é recusada

SituaçãoResposta
id inexistente ou de outra empresa404 · Factura não encontrada
Proforma (PP)400 · não é documento fiscal
FT já paga400 · anule primeiro o recibo
Documento não finalizado ou cancelado400 · Factura não finalizada
Data anterior à última NC da série500 · com a mensagem

Para o PDF da nota, use /siga/invoice/pdf com o note.id e doc: "invoice" (A4) ou "invoicemini" (talão).

Pedido
curl -X POST https://api.zcomercial.com/siga/invoice/creditnote \
  -H "Authorization: A1B2C3D4E5" \
  -H "Content-Type: application/json" \
  -d '{
  "note": {
    "invoice": "66f0c1a2b3c4d",
    "reason": "Anulação do pagamento",
    "date": "2026-09-30"
  }
}'
Campos de note
invoice  obrigatório · id da factura (da emissão)
reason   opcional · motivo; por omissão, as
         observações da factura
date     opcional · AAAA-MM-DD; por omissão, hoje
Resposta200
{
  "note": {
    "id": "66fa1b77c02e4",
    "sequence_number": "NC 2026/12",
    "numero_agt": "",
    "saft_hash": "Qx7d",
    "status": "Final",
    "type": "Anulação",
    "date": "2026-09-30",
    "valor": "134520",
    "invoice": "66f0c1a2b3c4d",
    "invoice_number": "FT 2026/104",
    "already_existed": false
  }
}
FT já paga400
{
  "status": false,
  "message": "Não é possível criar uma nota de crédito a partir de uma factura paga. Tem de cancelar o recibo"
}
Consulta

Listar facturas

GET/v1/invoice/index/{id}/{offset}/{limit}/{data}
GET/siga/invoice/index/{id}/{offset}/{limit}/{data}

Devolve as facturas da empresa (FT, FR e PP; recibos e notas não entram), da mais recente para a mais antiga. Todos os segmentos são opcionais e posicionais:

SegmentoSignificado
idO id de uma factura, para obter só essa. Use 0 para não filtrar.
offsetQuantas saltar. Por omissão, 0.
limitQuantas devolver. Por omissão, 20; na v1, no máximo 100.
dataSó as facturas deste dia (AAAA-MM-DD).

GET /v1/invoice sem segmentos devolve as 20 mais recentes.

Uma factura
GET /v1/invoice/index/66f0c1a2b3c4d
Facturas de um dia, 100 de cada vez
GET /v1/invoice/index/0/0/100/2026-09-30
Resposta200
{
  "invoice": [ { "id": "66f0c1a2b3c4d", "sequence_number": "FT 2026/104", ... } ],
  "meta": { "total_count": 1, "offset": 0, "limit": 100 }
}
Nota
Nas listagens o cliente vem em "custumer"
(grafia histórica); na emissão, em "client".
Documentos

Gerar PDF

POST/v1/invoice/pdf
POST/siga/invoice/pdf

Gera o PDF oficial do documento e devolve o endereço onde fica disponível.

CampoDescrição
pdf.id obrig.O id do documento.
pdf.doc obrig.invoice — factura ou nota de crédito em A4 · invoicemini — talão de 80 mm · receipt — recibo (A4).
pdf.second_copy opc.1 para marcar como «2.ª Via». Por omissão, original.

O A4 inclui as vias (original, duplicado, triplicado) configuradas na empresa. Com Facturação Electrónica, o documento leva o número AGT e o QR de validação.

Pedido
{
  "pdf": {
    "id": "66f0c1a2b3c4d",
    "doc": "invoicemini",
    "second_copy": 0
  }
}
Resposta200
{
  "pdf": {
    "invoice_url": "https://api.zcomercial.com/static/pdf/Factura..._FT_2026_104.pdf"
  }
}
Documentos

Enviar por email

POST/v1/invoice/send
POST/siga/invoice/send

Envia o PDF (A4) ao cliente, com uma mensagem padrão em nome da empresa seguida do texto de body. Responde 200 sem corpo.

CampoDescrição
message.doc obrig.invoice ou receipt.
message.id obrig.O id do documento.
message.subject obrig.Assunto.
message.client.email obrig.Destinatário.
message.body opc.Texto acrescentado à mensagem.
message.cc / bcc opc.Cópias.
hash opc.Repita aqui o id: é usado para pôr o nome do cliente na saudação.
Pedido
{
  "message": {
    "doc": "invoice",
    "id": "66f0c1a2b3c4d",
    "subject": "Factura FT 2026/104",
    "body": "Pagamento por transferência para o IBAN indicado.",
    "client": { "email": "compras@cliente.co.ao" },
    "cc": "",
    "bcc": ""
  },
  "hash": "66f0c1a2b3c4d"
}
Referência

Esquemas

Factura — invoice

CampoDescrição
type obrig.FT, FR ou PP.
date obrig.Data do documento, AAAA-MM-DD. Não pode ser anterior à do último documento finalizado da mesma série e tipo.
items obrig.Linhas (pelo menos uma).
client opc.Cliente. Sem ele: Consumidor final.
payment_mechanismSó FR. Obrigatório na siga; na v1, por omissão OU.
serie opc.Só v1. Série a usar; por omissão, a activa.
observations opc.Impressas no documento.
reference opc.Referência do cliente (ex.: nº de encomenda).
mx_reference opc.{ "entity", "reference" } — referência de pagamento Multicaixa impressa no documento.

A data de vencimento é calculada pelo prazo configurado na empresa. O imposto aplicado é o imposto activo da empresa; os campos tax, tax_exemption, due_date e currency_code não são lidos.

Cliente — invoice.client

CampoDescrição
fiscal_id obrig.NIF. Se já existe na empresa, usa-se esse cliente e os restantes campos são ignorados.
addressObrigatório quando o NIF é novo na empresa.
email, phone opc.Contactos.
postal_code, city, country, website, fax, mobile, short_name opc. Em falta, ficam com «-».
nameIgnorado: usa-se o nome oficial do NIF.

Linha — invoice.items[]

CampoDescrição
name obrig.Nome do artigo (identifica-o — ver Artigos).
unit_price obrig.Preço unitário sem imposto, maior que 0.
quantity obrig.Quantidade, maior que 0.
type obrig.P produto (desconta stock) ou S serviço.
discountDesconto em percentagem, 0–100. Envie sempre (0 se não houver).
descriptionDescrição da linha, impressa no documento. Envie sempre (pode repetir o nome).

Pagamento — payment

CampoDescrição
invoice obrig.id da factura FT.
amount obrig.Valor pago, maior que 0 e até ao valor em dívida.
payment_date obrig.AAAA-MM-DD.
payment_mechanism obrig.Ver Meios de pagamento.
note opc.Observação do recibo.
Linha devolvida (items[])
{
  "name": "Consultoria",
  "description": "Setembro",
  "unit_price": "50000",
  "quantity": "2",
  "tax": { "id": "1", "name": "IVA", "value": "14" },
  "discount": "0",
  "subtotal": 100000,
  "tax_amount": "14",
  "total": 100014
}
Nas linhas devolvidas, tax_amount e total não trazem o valor do imposto: tax_amount repete a taxa (%). Para totais use o valor do documento, que é o valor fiscal (o do PDF e o comunicado à AGT).
Datas e números
datas    AAAA-MM-DD
valores  números com ponto decimal (50000.50)
nas respostas, muitos números vêm como texto
Referência

Meios de pagamento

Códigos aceites em payment_mechanism (Factura-Recibo e recibos):

CódigoMeio
NUNumerário
TBTransferência bancária
MBMulticaixa (referência ou TPA)
CDCartão de débito
CCCartão de crédito
CHCheque
DEDinheiro electrónico
OUOutros
Exemplo
"payment_mechanism": "MB"
Referência

Erros

Os erros vêm como {"status": false, "message": "…"}, excepto a chave inválida, que devolve só o texto "Not Found". Use a message para mostrar ao utilizador ou registar; os textos estão em português.

HTTPQuando
200Sucesso. Na v1, confirme que o corpo tem o documento e não "status": false.
202v1: emissão ainda em curso — consultar estado.
400v1: dados inválidos ou emissão recusada. NC: factura em estado que não a permite.
404Chave inválida, subscrição expirada, documento não encontrado. Na faceta siga e no pagamento, também os erros de validação.
409Pedido duplicado (mesmo corpo nas últimas 24 horas).
500Falha interna. NC: a nota não pôde ser finalizada (a mensagem diz porquê).

Mensagens mais comuns

MensagemO que fazer
… é obrigatórioFalta o campo indicado, ou veio vazio ou a 0.
Erro na confirmação do NIF do clienteNIF inexistente na AGT, ou serviço indisponível. Verifique o NIF e tente mais tarde.
Já atingiu o número máximo de documentosLimite do plano. Contacte o zComercial.
Dados da empresa incompletoA empresa tem de completar NIF, morada, cidade e regime no zComercial.
… data inferior a facturas finalizadasA data é anterior à do último documento da série.
Erro de validação400
{
  "status": false,
  "message": "Erro, não pode registar item com desconto maior que 100%"
}
Boas práticas
• guarde o id de cada documento
• em 202, consulte o estado — não reenvie
• em timeout, consulte antes de repetir
• emita pela ordem das datas
• um nome de artigo = um preço
Compatibilidade

Faceta v2 (legado)

Assíncrona: o pedido é aceite com 202 e um process_id, e o resultado consulta-se depois. Mantida para integrações existentes. Para novas integrações use a v1, que usa a mesma fila e devolve o documento na maioria dos casos.

POST/v2/Invoice/create
GET/v2/Invoice/invoicestatus/{process_id}
POST/v2/Invoice/payment
GET/v2/Invoice/paymentstatus/{process_id}
  • Todos os endpoints da v2 lêem a chave do cabeçalho Authorization2.
  • Só aceita type FT e PP.
  • O corpo é o mesmo da v1 (invoice / payment). O estado tem a forma descrita em Consultar estado.
Resposta202
{
  "status": true,
  "process_id": 12547
}
Estados
PENDING     na fila
PROCESSING  a emitir
DONE        terminado — ver result
ERROR       falhou — result tem a mensagem
zComercial · API de integração — facturação certificada AGT (Angola). Actualizado a 30/09/2026. Empresas migradas: API v3.