zComercial API v3 Facturação electrónica certificada AGT · Angola
Referência da API

zComercial · API v3

Emita documentos fiscais em massa por API. Toda a emissão é certificada AGT — a assinatura SAF-T e a Facturação Electrónica (FE) são tratadas automaticamente pelo zComercial. O integrador só envia o documento e recebe o número fiscal.

A API v3 é assíncrona: os pedidos de emissão são enfileirados e processados por um worker; o integrador consulta o resultado por polling. Isto sustenta grandes volumes sem timeouts.

A API está incluída nos planos Profissional (5.000 pedidos/dia) e Enterprise (ilimitado). Os planos Pequeno, Médio e Grande não incluem acesso à API.

Base URL e formato

  • Todos os pedidos e respostas são JSON (Content-Type: application/json).
  • Todas as chamadas usam HTTPS; HTTP simples falha.
Base URL
https://<o-seu-subdominio-api>/v3
Cabeçalhos em todos os pedidos
Content-Type: application/json
Authorization: zc_<token-da-firma>
Ciclo de emissão
1. POST v3/invoice/create   → job_id
2. GET  v3/invoice/status   → DONE + invoice.id
3. guardar invoice.id p/ pagar/notas

Autenticação

A API autentica por token de firma — uma chave estável, uma por empresa — enviada no cabeçalho Authorization de cada pedido.

Como obter o token

No zComercial: Integrações → API de integração → Gerar token de API. Guarde-o em local seguro. Regenerar o token invalida o anterior imediatamente.

Mantenha o token secreto. Ele autoriza a emissão de documentos fiscais em nome da sua empresa. Trate-o como uma palavra-passe.
Exemplo — pedido autenticado
curl https://api-v3.zcomercial.com/v3/invoice/create \
  -X POST \
  -H "Authorization: zc_a1b2c3d4e5f6a7b8c9d0" \
  -H "Content-Type: application/json" \
  -d @factura.json
Sem token / token inválido401
{ "status": false,
  "message": "Chave de API inválida." }

Conceitos

Tipos de documento

CódigoDocumento
FTFactura
FRFactura-Recibo (paga na hora)
PPFactura Proforma
RCRecibo (do pagamento de uma FT)
NC / NDNota de Crédito / Débito

SAF-T e FE são automáticos

Cada documento é assinado (SAF-T, RSA-SHA1, cadeia de hash) no momento da emissão. Se a firma está no regime de Facturação Electrónica, o documento é comunicado à AGT automaticamente após ser emitido — não há um pedido separado a fazer.

A referência id

Cada emissão devolve um campo id (um hash). Guarde-o: é a referência que usa depois para registar o pagamento, emitir uma nota ou cancelar o documento.

Estados de um documento
status: "Final"     // emitido, válido
status: "Pago"      // liquidado
status: "Cancelado" // anulado
Estados de um job (assíncrono)
PENDING → PROCESSING → DONE
                     ↳ ERROR
Passo 1

Emitir factura

POSTv3/invoice/create

Enfileira a emissão de uma factura e devolve um job_id. A emissão real (número fiscal, assinatura, comunicação AGT) é feita pelo worker; consulte o resultado em Consultar estado.

O corpo tem um objecto invoice. Os únicos campos obrigatórios são items (≥1 linha, cada uma com name). Ver Esquemas.

Emita cada documento uma só vez. Se um pedido expirar, consulte o estado do job antes de reenviar — evita duplicados.
Pedido
curl https://api-v3.zcomercial.com/v3/invoice/create \
  -X POST \
  -H "Authorization: zc_a1b2c3d4e5f6a7b8c9d0" \
  -H "Content-Type: application/json" \
  -d '{
    "invoice": {
      "type": "FT",
      "serie": "2026",
      "date": "2026-07-28",
      "observations": "Encomenda #4471",
      "client": { "fiscal_id": "5417222925" },
      "items": [
        {
          "name": "Consultoria",
          "unit_price": 50000,
          "quantity": 2,
          "discount": 0,
          "type": "S"
        },
        {
          "name": "Licença anual",
          "unit_price": 120000,
          "quantity": 1,
          "type": "P"
        }
      ]
    }
  }'
Resposta202 Accepted
{
  "status": true,
  "job_id": 89175,
  "status_url": "https://api-v3.zcomercial.com/v3/invoice/status/89175"
}
Passo 2

Consultar estado

GETv3/invoice/status/{job_id}

Consulte o estado do job por polling (com backoff). Enquanto PENDING ou PROCESSING, result é null. Quando DONE, result.invoice traz o documento emitido — guarde result.invoice.id. Em ERROR, result traz a mensagem.

Pedido
curl https://api-v3.zcomercial.com/v3/invoice/status/89175 \
  -H "Authorization: zc_a1b2c3d4e5f6a7b8c9d0"
Resposta200 OK
{
  "status": "DONE",
  "result": {
    "status": true,
    "invoice": {
      "id": "6a67f5b08d52c",
      "sequence_number": "FT 2026/10327",
      "status": "Final",
      "type": "Factura",
      "date": "2026-07-28",
      "saft_hash": "vwlV",
      "due_date": "2026-08-27",
      "currency": "AKZ",
      "valor": 250000,
      "client": {
        "id": 812,
        "name": "GLOBAL CATERING",
        "fiscal_id": "5417222925"
      },
      "items": [
        {
          "name": "Consultoria",
          "unit_price": 50000,
          "quantity": 2,
          "tax": { "id": 1, "name": "IVA", "value": 14 },
          "discount": 0,
          "subtotal": 100000,
          "total": 114000
        }
      ]
    }
  }
}

Registar pagamento

POSTv3/invoice/payment

Regista o pagamento de uma factura pela sua referência id e emite um Recibo (RC). Devolve um process_id; consulte o resultado em v3/invoice/payment/status/{process_id} (mesma forma de Consultar estado, com result.receipt).

Pagamentos parciais são aceites; ao atingir o total, a factura passa a Pago. O valor não pode exceder o devido.

Pedido
curl https://api-v3.zcomercial.com/v3/invoice/payment \
  -X POST \
  -H "Authorization: zc_a1b2c3d4e5f6a7b8c9d0" \
  -H "Content-Type: application/json" \
  -d '{
    "payment": {
      "invoice": "6a67f5b08d52c",
      "amount": 114000,
      "payment_date": "2026-07-28",
      "payment_mechanism": "TB"
    }
  }'
Resposta202 Accepted
{ "status": true, "process_id": 55012 }

Nota de crédito

POSTv3/invoice/credit-note

Emite uma Nota de Crédito sobre uma factura, referenciada pela sua id. Síncrono — devolve a nota emitida na mesma resposta (não usa fila).

A série e o cliente são herdados da factura de origem — não se indicam no corpo da nota.

A Nota de Crédito não pode exceder o valor em dívida da factura de origem.
Pedido
curl https://api-v3.zcomercial.com/v3/invoice/credit-note \
  -X POST \
  -H "Authorization: zc_a1b2c3d4e5f6a7b8c9d0" \
  -H "Content-Type: application/json" \
  -d '{
    "note": {
      "invoice": "6a67f5b08d52c",
      "reason": "Devolução parcial",
      "items": [
        { "name": "Consultoria", "unit_price": 50000, "quantity": 1 }
      ]
    }
  }'
Resposta200 OK
{
  "note": {
    "id": "6a67f5c7f1011",
    "sequence_number": "NC 2026/415",
    "status": "Final",
    "type": "Nota de Crédito",
    "kind": "Rectificação",
    "related": "FT 2026/10327",
    "saft_hash": "k2mP",
    "items": [ /* linhas da nota */ ]
  }
}

Nota de débito

POSTv3/invoice/debit-note

Emite uma Nota de Débito sobre uma factura (ex.: juros, encargos adicionais). Mesmo corpo da nota de crédito — note com invoice, reason e items. Síncrono; série e cliente herdados da origem.

Pedido
curl https://api-v3.zcomercial.com/v3/invoice/debit-note \
  -X POST \
  -H "Authorization: zc_a1b2c3d4e5f6a7b8c9d0" \
  -H "Content-Type: application/json" \
  -d '{
    "note": {
      "invoice": "6a67f5b08d52c",
      "reason": "Juros de mora",
      "items": [
        { "name": "Juros", "unit_price": 5000, "quantity": 1 }
      ]
    }
  }'
Resposta200 OK
{
  "note": {
    "id": "6a680b1c4d2e3",
    "sequence_number": "ND 2026/58",
    "status": "Final",
    "type": "Nota de Débito",
    "related": "FT 2026/10327",
    "saft_hash": "p9Rf",
    "items": [ /* ... */ ]
  }
}

Cancelar documento

POSTv3/invoice/cancel

Anula um documento fiscal (FT, RC, NC ou ND) pela sua id, indicando o motivo. O documento mantém-se no SAF-T com estado anulado, como exige a AGT. Se a firma está em FE, a anulação é comunicada à AGT (o campo fe_cancel_enqueued indica-o).

Pedido
curl https://api-v3.zcomercial.com/v3/invoice/cancel \
  -X POST \
  -H "Authorization: zc_a1b2c3d4e5f6a7b8c9d0" \
  -H "Content-Type: application/json" \
  -d '{
    "document": "6a67f5c7f1011",
    "reason": "Emitida por engano"
  }'
Resposta200 OK
{
  "document": {
    "sequence_number": "NC 2026/415",
    "type": "Nota de Crédito",
    "status": "Cancelado",
    "reason": "Emitida por engano"
  },
  "message": "Documento anulado.",
  "fe_cancel_enqueued": true
}

Esquemas

Item — items[]

CampoDescrição
namereqNome do artigo. Se não existir na firma, é criado.
unit_pricereqPreço unitário, sem IVA.
quantityreqQuantidade.
discountopcDesconto em percentagem (0–100). Default 0.
descriptionopcDescrição/observação da linha.
typeopcP produto / S serviço (default). Produtos debitam stock.

Factura — invoice

CampoDescrição
typeopcFT (default), FR ou PP.
serieopcSérie fiscal (opcional). Default: 1ª série activa da firma.
dateopcData (YYYY-MM-DD). Default: hoje.
client.fiscal_idopcNIF do cliente. Sem NIF → consumidor final.
itemsreqLista de linhas (≥1).
observationsopcObservações impressas.
payment_mechanismopcSó FR: meio de pagamento.
Pagamento — payment
CampoDescrição
invoice            id da factura (req)
amount             valor pago  (req)
payment_date       YYYY-MM-DD  (req)
payment_mechanism  ver meios   (req)
Nota — note
invoice  id da factura de origem (req)
reason   motivo                  (req)
items    linhas da nota          (req)
observations                     (opc)
Cancelar — corpo
document  id do documento (req)
reason    motivo          (req)

Meios de pagamento

Valores de payment_mechanism:

CódigoMeio
NUNumerário
TBTransferência bancária
MBMulticaixa
CDCartão de débito
CCCartão de crédito
CHCheque
OUOutros
Limite de pedidos (rate limit)
# cabeçalho em cada resposta
X-RateLimit-Limit: 5000

# Profissional → 5.000 / dia
# Enterprise   → ilimitado
Exceder a quota diária devolve 429. Distribua a emissão em massa ao longo do dia e respeite o cabeçalho X-RateLimit-Limit.

Erros

Respostas de erro têm código HTTP 4xx e o formato { "status": false, "message": "..." }.

HTTPCausa comum
401Token de API em falta ou inválido (Authorization).
400Payload inválido — invoice.items em falta, item sem name, ou note.invoice/document em falta.
404Job (assíncrono) não encontrado, ou de outra firma.
429Excedeu a quota diária de pedidos do plano.
Formato de erro4xx
{
  "status": false,
  "message": "Payload inválido: invoice.items em falta."
}
Boas práticas
• emitir cada documento uma só vez
• guardar o invoice.id de cada factura
• série é opcional (usa a 1ª activa)
• polling com backoff no status
zComercial · API v3 — facturação electrónica certificada AGT (Angola). As facetas v1/v2 mantêm-se por compatibilidade.