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:
| Faceta | Para 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. |
https://api.zcomercial.com
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)
Content-Type: application/json
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,mobileoushort_namepodia devolver uma página de erro ou sair em nome de «Consumidor final». Agora só são obrigatórios ofiscal_ide oaddress. - 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, compayment_mechanismobrigató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/createespera 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/createpassou a usar a fila de emissão. Devolve 200 com a factura, ou 202 com umprocess_idpara consultar depois. Ver Emitir factura.- Pedidos duplicados — o mesmo corpo enviado duas vezes em 24 horas é recusado com
409 e o
process_iddo 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.
{
"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"
}
{
"status": false,
"message": "Payload duplicado. Esta fatura já foi submetida recentemente.",
"process_id": 91823,
"status_url": "https://api.zcomercial.com/v2/Invoice/invoicestatus/91823"
}
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.
Authorization: <chave-da-empresa>
Authorization2: <chave-da-empresa>
Content-Type: application/json
curl https://api.zcomercial.com/v1/invoice \
-H "Authorization: A1B2C3D4E5" \
-H "Authorization2: A1B2C3D4E5"
"Not Found"
Conceitos
Tipos de documento
| Código | Documento | Como se emite |
|---|---|---|
| FT | Factura (paga depois) | invoice.type = "FT" |
| FR | Factura-Recibo (paga no acto) | invoice.type = "FR" |
| PP | Factura Proforma (não fiscal) | invoice.type = "PP" |
| RC | Recibo de uma FT | /invoice/payment |
| NC | Nota 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.
{
"invoice": {
"id": "66f0c1a2b3c4d", ← guardar
"sequence_number": "FT 2026/104",
"status": "Final",
...
}
}
Final emitido, por pagar (FT) ou proforma
Pago FR, ou FT paga pelos recibos
Cancelado anulado
Emitir factura (v1)
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_ide 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_iddevolvido para obter o documento original.
{"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).
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" }
]
}
}'
{
"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": "" }
}
}
{
"status": false,
"message": "Erro, não pode finalizar um rascunho com data inferior a facturas finalizadas"
}
Consultar estado
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:
| Campo | Significado |
|---|---|
| status | PENDING na fila · PROCESSING a emitir ·
DONE terminado · ERROR falhou |
| result | Em 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_em | Quando terminou. |
Consulte com intervalo crescente (1 s, 2 s, 4 s…). Normalmente o documento está pronto em poucos segundos.
curl https://api.zcomercial.com/v2/Invoice/invoicestatus/91823 \
-H "Authorization2: A1B2C3D4E5"
{
"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",
...
}
Emitir factura (siga)
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.
{
"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" }
]
}
}
{
"status": false,
"message": "Erro, payment_mechanism é obrigatório para Factura Recibo (FR)"
}
Registar pagamento
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.
{
"payment": {
"invoice": "66f0c1a2b3c4d",
"amount": 50000,
"payment_date": "2026-10-05",
"payment_mechanism": "TB",
"note": "1.ª prestação"
}
}
{
"receipt": {
"id": "66f2a9e01d7b3",
"sequence_number": "RC 2026/57",
"status": "Pago",
"type": "Recibo",
"date": "2026-10-05",
"valor": "50000",
"custumer": { ... },
"items": [ ... ]
}
}
{
"status": false,
"message": "Erro ao tentar alterar os dados, pagamento superior ao valor da factura"
}
Nota de crédito
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": trueem 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ção | Resposta |
|---|---|
| id inexistente ou de outra empresa | 404 · Factura não encontrada |
| Proforma (PP) | 400 · não é documento fiscal |
| FT já paga | 400 · anule primeiro o recibo |
| Documento não finalizado ou cancelado | 400 · Factura não finalizada |
| Data anterior à última NC da série | 500 · com a mensagem |
Para o PDF da nota, use /siga/invoice/pdf com o note.id e
doc: "invoice" (A4) ou "invoicemini" (talão).
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"
}
}'
noteinvoice 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
{
"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
}
}
{
"status": false,
"message": "Não é possível criar uma nota de crédito a partir de uma factura paga. Tem de cancelar o recibo"
}
Listar facturas
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:
| Segmento | Significado |
|---|---|
| id | O id de uma factura, para obter só essa. Use 0
para não filtrar. |
| offset | Quantas saltar. Por omissão, 0. |
| limit | Quantas devolver. Por omissão, 20; na v1, no máximo 100. |
| data | Só as facturas deste dia (AAAA-MM-DD). |
GET /v1/invoice sem segmentos devolve as 20 mais recentes.
GET /v1/invoice/index/66f0c1a2b3c4d
GET /v1/invoice/index/0/0/100/2026-09-30
{
"invoice": [ { "id": "66f0c1a2b3c4d", "sequence_number": "FT 2026/104", ... } ],
"meta": { "total_count": 1, "offset": 0, "limit": 100 }
}
Nas listagens o cliente vem em "custumer"
(grafia histórica); na emissão, em "client".
Gerar PDF
Gera o PDF oficial do documento e devolve o endereço onde fica disponível.
| Campo | Descriçã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.
{
"pdf": {
"id": "66f0c1a2b3c4d",
"doc": "invoicemini",
"second_copy": 0
}
}
{
"pdf": {
"invoice_url": "https://api.zcomercial.com/static/pdf/Factura..._FT_2026_104.pdf"
}
}
Enviar por email
Envia o PDF (A4) ao cliente, com uma mensagem padrão em nome da empresa seguida do texto
de body. Responde 200 sem corpo.
| Campo | Descriçã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. |
{
"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"
}
Esquemas
Factura — invoice
| Campo | Descriçã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_mechanism | Só 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
| Campo | Descrição |
|---|---|
| fiscal_id obrig. | NIF. Se já existe na empresa, usa-se esse cliente e os restantes campos são ignorados. |
| address | Obrigató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 «-». |
| name | Ignorado: usa-se o nome oficial do NIF. |
Linha — invoice.items[]
| Campo | Descriçã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. |
| discount | Desconto em percentagem, 0–100. Envie sempre (0 se não houver). |
| description | Descrição da linha, impressa no documento. Envie sempre (pode repetir o nome). |
Pagamento — payment
| Campo | Descriçã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. |
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
}
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 AAAA-MM-DD
valores números com ponto decimal (50000.50)
nas respostas, muitos números vêm como texto
Meios de pagamento
Códigos aceites em payment_mechanism (Factura-Recibo e recibos):
| Código | Meio |
|---|---|
| NU | Numerário |
| TB | Transferência bancária |
| MB | Multicaixa (referência ou TPA) |
| CD | Cartão de débito |
| CC | Cartão de crédito |
| CH | Cheque |
| DE | Dinheiro electrónico |
| OU | Outros |
"payment_mechanism": "MB"
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.
| HTTP | Quando |
|---|---|
| 200 | Sucesso. Na v1, confirme que o corpo tem o documento e não
"status": false. |
| 202 | v1: emissão ainda em curso — consultar estado. |
| 400 | v1: dados inválidos ou emissão recusada. NC: factura em estado que não a permite. |
| 404 | Chave inválida, subscrição expirada, documento não encontrado. Na faceta siga e no pagamento, também os erros de validação. |
| 409 | Pedido duplicado (mesmo corpo nas últimas 24 horas). |
| 500 | Falha interna. NC: a nota não pôde ser finalizada (a mensagem diz porquê). |
Mensagens mais comuns
| Mensagem | O que fazer |
|---|---|
| … é obrigatório | Falta o campo indicado, ou veio vazio ou a 0. |
| Erro na confirmação do NIF do cliente | NIF inexistente na AGT, ou serviço indisponível. Verifique o NIF e tente mais tarde. |
| Já atingiu o número máximo de documentos | Limite do plano. Contacte o zComercial. |
| Dados da empresa incompleto | A empresa tem de completar NIF, morada, cidade e regime no zComercial. |
| … data inferior a facturas finalizadas | A data é anterior à do último documento da série. |
{
"status": false,
"message": "Erro, não pode registar item com desconto maior que 100%"
}
• 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
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.
- Todos os endpoints da v2 lêem a chave do cabeçalho
Authorization2. - Só aceita
typeFTePP. - O corpo é o mesmo da v1 (
invoice/payment). O estado tem a forma descrita em Consultar estado.
{
"status": true,
"process_id": 12547
}
PENDING na fila
PROCESSING a emitir
DONE terminado — ver result
ERROR falhou — result tem a mensagem