Billing Core API
Motor de faturacao fiscal multi-tenant certificavel pela Autoridade Tributaria (AT) de Portugal. API RESTful com autenticacao JWT/OAuth2, documentos fiscais com assinatura digital RSA-SHA1, cadeia de hash, ATCUD, QR Code e SAF-T PT.
Base URL
Tipos de Documento Suportados
Autenticacao
Todos os endpoints requerem autenticacao via header Authorization. O Billing Core suporta dois metodos:
| Metodo | Uso | Validade |
|---|---|---|
| JWT | Utilizadores (email + password) | Access: 15 min / Refresh: 7 dias |
| OAuth2 | Apps (client_id + client_secret) | 1 hora |
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Erros
A API utiliza codigos HTTP convencionais para indicar sucesso ou falha.
| Codigo | Nome | Descricao |
|---|---|---|
| 400 | Bad Request | Dados invalidos ou Idempotency-Key ausente |
| 401 | Unauthorized | Token ausente, invalido ou expirado |
| 403 | Forbidden | Sem permissao para este recurso |
| 404 | Not Found | Recurso nao encontrado |
| 409 | Conflict | Documento ja committed/cancelado |
| 422 | Validation Error | Campos obrigatorios em falta |
| 429 | Too Many Requests | Rate limit excedido |
Paginacao
Todos os endpoints de listagem suportam paginacao via query parameters.
| Parametro | Tipo | Default | Descricao |
|---|---|---|---|
| page | integer | 1 | Numero da pagina |
| page_size | integer | 20 | Itens por pagina (max 100) |
{
"items": [...],
"total": 150,
"page": 1,
"page_size": 20
}
Idempotencia
Endpoints que modificam estado requerem o header Idempotency-Key com um identificador unico. Respostas sao cacheadas durante 24 horas.
Idempotency-Key: ordem-compra-12345-v1
Login (JWT)
Autenticacao de utilizador por email e password. Retorna access token (15 min) e refresh token (7 dias).
Parametros
| Campo | Tipo | Descricao |
|---|---|---|
| emailobrigatorio | string | Email do utilizador |
| passwordobrigatorio | string | Password (min 8 caracteres) |
curl -X POST https://api.billingcore.pt/api/v1/auth/login \ -H "Content-Type: application/json" \ -d '{ "email": "admin@empresa.pt", "password": "senha-segura" }'
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"expires_in": 900
}
Refresh Token
Renovar access token usando refresh token. O refresh token tem validade de 7 dias.
| Campo | Tipo | Descricao |
|---|---|---|
| refresh_tokenobrigatorio | string | Refresh token obtido no login |
OAuth2 Client Credentials (Apps)
Autenticacao de app por client_id e client_secret. Retorna access token com validade de 1 hora.
| Campo | Tipo | Descricao |
|---|---|---|
| grant_typeobrigatorio | string | Deve ser client_credentials |
| client_idobrigatorio | string | ID da app |
| client_secretobrigatorio | string | Secret da app |
curl -X POST https://api.billingcore.pt/api/v1/auth/token \ -H "Content-Type: application/json" \ -d '{ "grant_type": "client_credentials", "client_id": "uuid-da-app", "client_secret": "secret-da-app" }'
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"expires_in": 3600
}
Documentos
Criar Documento
Criar documento fiscal em estado DRAFT. O documento fica em DRAFT ate ser committed via POST /documents/{id}/commit. Header Idempotency-Key obrigatorio.
original_document_id obrigatorio.| Campo | Tipo | Descricao |
|---|---|---|
| typeobrigatorio | string | FT, FR, FS, RC, ND, NC |
| series_idobrigatorio | uuid | ID da serie |
| customer_idobrigatorio | uuid | ID do cliente |
| invoice_dateobrigatorio | date | Data da fatura (YYYY-MM-DD) |
| linesobrigatorio | array | Linhas do documento (min 1) |
| original_document_id | uuid | FT original (obrigatorio para RC e ND) |
| payment_amount | decimal | Valor pago (RC parcial) |
Objeto linha
| Campo | Tipo | Descricao |
|---|---|---|
| product_id | uuid | ID do produto (opcional) |
| descriptionobrigatorio | string | Descricao da linha |
| quantityobrigatorio | decimal | Quantidade (3 decimais) |
| unit_priceobrigatorio | decimal | Preco unitario |
| tax_rateobrigatorio | decimal | Taxa IVA (ex: 23.00) |
curl -X POST https://api.billingcore.pt/api/v1/documents \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: unique-key-123" \ -d '{ "type": "FT", "series_id": "uuid-da-serie", "customer_id": "uuid-do-cliente", "invoice_date": "2026-04-09", "lines": [ { "product_id": "uuid-do-produto", "description": "Servico de Consultoria", "quantity": "2.000", "unit_price": "100.00", "tax_rate": "23.00" } ] }'
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "FT",
"status": "DRAFT",
"document_no": null,
"invoice_date": "2026-04-09",
"gross_total": null,
"hash": null,
"atcud": null,
"lines": [...]
}
Listar Documentos
Listar documentos do tenant com filtros e paginacao.
| Parametro | Tipo | Descricao |
|---|---|---|
| status | string | Filtrar por status (DRAFT, COMMITTED, CANCELLED) |
| type | string | Filtrar por tipo (FT, NC, etc.) |
| series_id | uuid | Filtrar por serie |
| customer_id | uuid | Filtrar por cliente |
Obter Documento
Retorna documento com todas as linhas. Filtrado pelo tenant autenticado.
Atualizar Documento
Atualizar documento em estado DRAFT. Documentos COMMITTED ou CANCELLED sao imutaveis.
Eliminar Documento
Eliminar documento em DRAFT. Documentos COMMITTED ou CANCELLED nao podem ser eliminados.
Commit Fiscal
Transforma documento DRAFT em COMMITTED. Processo irreversivel que inclui: calculo de totais, numeracao sequencial, assinatura RSA-SHA1, ATCUD e QR Code.
Idempotency-Key obrigatorio.Sequencia atomica
- Lock pessimista na serie (SELECT FOR UPDATE)
- Calcular totais (net, tax, gross)
- Atribuir numero sequencial
- Buscar previous_hash (cadeia de hash)
- Assinar com RSA-SHA1 (PKCS1v15)
- Gerar ATCUD e QR Code
- Marcar COMMITTED
curl -X POST https://api.billingcore.pt/api/v1/documents/{id}/commit \ -H "Authorization: Bearer <token>" \ -H "Idempotency-Key: commit-unique-key"
{
"message": "Document committed successfully",
"document": {
"id": "550e8400-...",
"type": "FT",
"status": "COMMITTED",
"document_no": 1,
"gross_total": "246.00",
"tax_total": "46.00",
"net_total": "200.00",
"hash": "base64-rsa-sha1-signature...",
"atcud": "ABCD1234-1",
"qr_payload": "A:500000001*B:999999990*..."
}
}
Cancelar Documento
Cancelar documento COMMITTED. O cancelamento e irreversivel. O campo reason e obrigatorio. Campos fiscais permanecem imutaveis.
| Campo | Tipo | Descricao |
|---|---|---|
| reasonobrigatorio | string | Motivo do cancelamento (max 500 chars) |
Nota de Credito
Criar nota de credito (NC) referenciando fatura original. Criada em DRAFT, deve ser committed separadamente. So pode referenciar faturas (FT) COMMITTED.
| Campo | Tipo | Descricao |
|---|---|---|
| original_document_idobrigatorio | uuid | ID da fatura original (FT COMMITTED) |
| series_idobrigatorio | uuid | ID da serie |
| invoice_dateobrigatorio | date | Data da nota de credito |
| reasonobrigatorio | string | Motivo da nota de credito |
| linesobrigatorio | array | Linhas (min 1) |
Descarregar PDF
Obter URL publico de download do PDF. Retorna JSON com download_url.
Descarregar ficheiro PDF com QR code embebido. Inclui dados do emitente, cliente, linhas, totais, ATCUD e hash. So documentos COMMITTED ou CANCELLED.
Clientes
Criar Cliente
Criar cliente. O NIF e validado pelo algoritmo mod 11 portugues.
| Campo | Tipo | Descricao |
|---|---|---|
| nameobrigatorio | string | Nome do cliente |
| nif | string | NIF portugues (9 digitos, validado) |
| address | object | Morada (street, city, postal_code, country) |
| tax_exempt | boolean | Isento de IVA (default: false) |
curl -X POST https://api.billingcore.pt/api/v1/customers \ -H "Authorization: Bearer <token>" \ -H "Content-Type: application/json" \ -d '{ "name": "Empresa XYZ Lda.", "nif": "999999990", "address": { "street": "Rua da Liberdade 100", "city": "Lisboa", "postal_code": "1250-096", "country": "PT" } }'
Listar Clientes
Listar clientes com paginacao. Filtros: nif, search (pesquisa por nome).
Obter Cliente
Obter cliente por ID.
Atualizar Cliente
Atualizar campos do cliente. Todos os campos sao opcionais.
Remover Cliente
Remover cliente. Falha com 409 se tiver documentos associados.
Produtos
Criar Produto
Criar produto/servico.
| Campo | Tipo | Descricao |
|---|---|---|
| codeobrigatorio | string | Codigo do produto |
| nameobrigatorio | string | Nome |
| priceobrigatorio | decimal | Preco unitario |
| tax_code | string | Codigo IVA: NOR, INT, RED, ISE (default: NOR) |
| unit | string | Unidade (default: UN) |
Listar Produtos
Listar produtos. Filtros: code, is_active, search.
Obter Produto
Obter produto por ID.
Atualizar Produto
Atualizar campos do produto.
Desativar Produto
Desativar produto (soft delete). O produto nao e eliminado, apenas marcado como inativo.
Series
Criar Serie
Criar serie de documentos.
| Campo | Tipo | Descricao |
|---|---|---|
| codeobrigatorio | string | Codigo da serie (ex: FT2026) |
| prefix | string | Prefixo (ex: FT) |
| validation_code | string | Codigo ATCUD da AT |
Listar Series
Listar series. Filtro: status (active, suspended, closed).
Obter Serie
Obter serie por ID.
Atualizar Serie
Atualizar serie (status, validation_code). Transicoes: active → suspended → closed. Serie fechada nao pode ser reaberta.
Utilizadores
Criar Utilizador
Criar utilizador. Email deve ser unico dentro do tenant.
| Campo | Tipo | Descricao |
|---|---|---|
| emailobrigatorio | string | Email (unico por tenant) |
| passwordobrigatorio | string | Password (min 8 chars) |
| role | string | admin, operator, viewer (default: viewer) |
Listar Utilizadores
Listar utilizadores. Filtros: role, is_active.
Obter Utilizador
Obter utilizador por ID.
Atualizar Utilizador
Atualizar role ou estado do utilizador.
Desativar Utilizador
Desativar utilizador (soft delete).
Apps OAuth2
Criar App
Criar app OAuth2. O client_secret so e retornado nesta resposta — guardar de imediato.
| Campo | Tipo | Descricao |
|---|---|---|
| nameobrigatorio | string | Nome da app |
| webhook_url | string | URL para webhooks |
| scopes | array | Lista de scopes (ex: documents:write) |
Listar Apps
Listar apps do tenant.
Obter App
Obter app por ID.
Atualizar App
Atualizar nome, webhook_url ou scopes.
Remover App
Remover app permanentemente.
SAF-T
Exportar SAF-T
Solicitar exportacao SAF-T PT (assincrona). Conforme Portaria 321-A/2007 (v1.04_01). O ficheiro XML e gerado em background.
| Campo | Tipo | Descricao |
|---|---|---|
| start_dateobrigatorio | date | Inicio do periodo |
| end_dateobrigatorio | date | Fim do periodo |
{
"id": "uuid-do-export",
"status": "pending",
"start_date": "2026-01-01",
"end_date": "2026-12-31"
}Estado da Exportacao
Verificar estado: pending, processing, completed, failed.
Descarregar SAF-T
Obter URL de download do ficheiro XML. So disponivel apos status completed.
Estatisticas
Obter Estatisticas
Estatisticas agregadas do tenant. Revenue so conta documentos COMMITTED (subtrai NC). DRAFT excluido por default.
| Parametro | Tipo | Descricao |
|---|---|---|
| start_date | date | Inicio do periodo (default: 1 Jan ano corrente) |
| end_date | date | Fim do periodo (default: hoje) |
| include_drafts | boolean | Incluir documentos DRAFT (default: false) |
curl "https://api.billingcore.pt/api/v1/stats?start_date=2026-01-01&end_date=2026-12-31" \ -H "Authorization: Bearer <token>"
{
"period": { "start": "2026-01-01", "end": "2026-12-31" },
"documents": {
"total": 150,
"by_type": { "FT": 100, "FR": 20, "NC": 5 },
"by_status": { "COMMITTED": 140, "CANCELLED": 10 }
},
"revenue": {
"gross_total": "18500.00",
"net_total": "15041.46",
"tax_total": "3458.54",
"currency": "EUR"
},
"top_customers": [
{
"customer_id": "uuid",
"name": "Cliente X",
"gross_total": "5000.00",
"document_count": 10
}
],
"series": [
{
"series_id": "uuid",
"code": "FT2026",
"last_document_no": 100,
"status": "active"
}
]
}