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.
Base URL e formato
- Todos os pedidos e respostas são JSON (
Content-Type: application/json). - Todas as chamadas usam HTTPS; HTTP simples falha.
https://<o-seu-subdominio-api>/v3
Content-Type: application/json
Authorization: zc_<token-da-firma>
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.
curl https://api-v3.zcomercial.com/v3/invoice/create \
-X POST \
-H "Authorization: zc_a1b2c3d4e5f6a7b8c9d0" \
-H "Content-Type: application/json" \
-d @factura.json
{ "status": false,
"message": "Chave de API inválida." }
Conceitos
Tipos de documento
| Código | Documento |
|---|---|
| FT | Factura |
| FR | Factura-Recibo (paga na hora) |
| PP | Factura Proforma |
| RC | Recibo (do pagamento de uma FT) |
| NC / ND | Nota 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.
status: "Final" // emitido, válido
status: "Pago" // liquidado
status: "Cancelado" // anulado
PENDING → PROCESSING → DONE
↳ ERROR
Emitir factura
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.
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"
}
]
}
}'
{
"status": true,
"job_id": 89175,
"status_url": "https://api-v3.zcomercial.com/v3/invoice/status/89175"
}
Consultar estado
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.
curl https://api-v3.zcomercial.com/v3/invoice/status/89175 \
-H "Authorization: zc_a1b2c3d4e5f6a7b8c9d0"
{
"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
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.
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"
}
}'
{ "status": true, "process_id": 55012 }
Nota de crédito
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.
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 }
]
}
}'
{
"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
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.
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 }
]
}
}'
{
"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
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).
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"
}'
{
"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[]
| Campo | Descrição | |
|---|---|---|
| name | req | Nome do artigo. Se não existir na firma, é criado. |
| unit_price | req | Preço unitário, sem IVA. |
| quantity | req | Quantidade. |
| discount | opc | Desconto em percentagem (0–100). Default 0. |
| description | opc | Descrição/observação da linha. |
| type | opc | P produto / S serviço (default). Produtos debitam stock. |
Factura — invoice
| Campo | Descrição | |
|---|---|---|
| type | opc | FT (default), FR ou PP. |
| serie | opc | Série fiscal (opcional). Default: 1ª série activa da firma. |
| date | opc | Data (YYYY-MM-DD). Default: hoje. |
| client.fiscal_id | opc | NIF do cliente. Sem NIF → consumidor final. |
| items | req | Lista de linhas (≥1). |
| observations | opc | Observações impressas. |
| payment_mechanism | opc | Só FR: meio de pagamento. |
| Campo | Descrição |
|---|
invoice id da factura (req)
amount valor pago (req)
payment_date YYYY-MM-DD (req)
payment_mechanism ver meios (req)
invoice id da factura de origem (req)
reason motivo (req)
items linhas da nota (req)
observations (opc)
document id do documento (req)
reason motivo (req)
Meios de pagamento
Valores de payment_mechanism:
| Código | Meio |
|---|---|
| NU | Numerário |
| TB | Transferência bancária |
| MB | Multicaixa |
| CD | Cartão de débito |
| CC | Cartão de crédito |
| CH | Cheque |
| OU | Outros |
# cabeçalho em cada resposta
X-RateLimit-Limit: 5000
# Profissional → 5.000 / dia
# Enterprise → ilimitado
X-RateLimit-Limit.Erros
Respostas de erro têm código HTTP 4xx e o formato
{ "status": false, "message": "..." }.
| HTTP | Causa comum |
|---|---|
| 401 | Token de API em falta ou inválido (Authorization). |
| 400 | Payload inválido — invoice.items em falta, item sem name, ou note.invoice/document em falta. |
| 404 | Job (assíncrono) não encontrado, ou de outra firma. |
| 429 | Excedeu a quota diária de pedidos do plano. |
{
"status": false,
"message": "Payload inválido: invoice.items em falta."
}
• 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
v1/v2 mantêm-se por compatibilidade.