A API pública da 4invoices envia os dados de faturamento do seu sistema para a 4invoices e, na Roménia, leva a fatura até ao fim no SPV da ANAF. Um único host de produção, um fluxo client_credentials, escritas fiscais idempotentes e o mesmo envelope de erro em todas as rotas.
https://api.4invoices.net/v1 · Especificação OpenAPI (sem chave)
O que é a API 4invoices
- A API pública da 4invoices é REST sobre HTTPS, com JSON à entrada e JSON à saída.
- Um único host de produção: https://api.4invoices.net/v1. Não existe um host de testes separado.
- A especificação OpenAPI 3.1 é pública e não exige chave: importe-a diretamente no Postman ou num gerador de clientes.
- Cada resposta inclui o cabeçalho X-Request-Id; indique-o sempre que pedir suporte.
- Todas as escritas fiscais são idempotentes: uma nova tentativa após um timeout nunca emite um segundo documento.
- Para a Roménia, o ciclo completo da e-Factura com a ANAF através da API: validação prévia, submissão, acompanhamento, resposta assinada e caixa de entrada. Nenhum concorrente romeno oferece isto.
- O SmartBill não tem nenhum endpoint para submissão no sistema nacional de faturamento eletrônico (ANAF, na Roménia) — o envio para o SPV é uma definição de conta disponível apenas na interface — nem qualquer endpoint de listagem de faturas.
- O Oblio só consegue criar clientes e produtos como efeito secundário da emissão de um documento, e não como recursos de primeira classe.
- Geração do XML UBL / CIUS-RO (Roménia) sem submissão: obtém o documento legal como arquivo sem tocar no SPV romeno.
- Idempotência nas escritas fiscais: uma nova tentativa após um timeout não produz uma segunda fatura nem gasta um segundo número.
- Uma caixa de entrada de faturas de fornecedores legível por programa — a base para uma reconciliação automatizada.
A primeira fatura em 6 passos
- Gere uma credencial no painel, em Faturamento → Definições → Acesso à API, e copie o client_secret — é mostrado uma única vez.
- Complete o perfil da empresa e ative pelo menos uma série do tipo fiscale, caso contrário a emissão devolve issuer_profile_incomplete ou no_series_configured.
- Gere uma credencial no painel, em Faturamento → Definições → Acesso à API, e copie o client_secret — é mostrado uma única vez.
- Complete o perfil da empresa e ative pelo menos uma série do tipo fiscale, caso contrário a emissão devolve issuer_profile_incomplete ou no_series_configured.
- Troque a credencial por um token: POST /v1/auth/token com grant_type client_credentials. O token dura uma hora — guarde-o em cache, não peça um por cada pedido.
- Emita a fatura: POST /v1/invoices com o cabeçalho Idempotency-Key e vat_rate em percentagem (21, não 0.21).
- Para o mercado romeno, execute a pré-validação CIUS-RO com POST /v1/invoices/{id}/efactura/validate e envie à ANAF com POST /v1/invoices/{id}/efactura/submit.
- Acompanhe o estado com GET /v1/efactura/submissions/{id} até chegar a accepted ou rejected.
bash
# 1 — token (1 hora, salvar em cache)
ACCESS_TOKEN=$(curl -sS -X POST https://api.4invoices.net/v1/auth/token \
-H 'Content-Type: application/json' \
-d '{"grant_type":"client_credentials","client_id":"cli_XXX","client_secret":"sec_XXX"}' \
| python3 -c 'import sys,json; print(json.load(sys.stdin)["access_token"])')
# 2 — emitir a fatura (Idempotency-Key é OBRIGATÓRIO)
curl -sS -X POST https://api.4invoices.net/v1/invoices \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: order-10457-invoice' \
-d '{"buyer":{"name":"Exemplu Comert SRL","tax_id":"RO12345678","county":"Cluj","city":"Cluj-Napoca","country":"RO"},
"lines":[{"description":"Abonament SaaS","quantity":1,"unit_price":400,"vat_rate":21}]}'
# 3 — preflight CIUS-RO, then send to ANAF
curl -sS -X POST https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/validate \
-H "Authorization: Bearer $ACCESS_TOKEN"
curl -sS -X POST https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/submit \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Idempotency-Key: efactura-inv_01J7ABC-1'javascript
const BASE = "https://api.4invoices.net/v1";
const token = await fetch(`${BASE}/auth/token`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
grant_type: "client_credentials",
client_id: process.env.FOURINVOICES_CLIENT_ID,
client_secret: process.env.FOURINVOICES_CLIENT_SECRET,
}),
}).then((r) => r.json()).then((d) => d.access_token);
const invoice = await fetch(`${BASE}/invoices`, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
"Idempotency-Key": `order-${orderId}-invoice`,
},
body: JSON.stringify({
buyer: { name: "Exemplu Comert SRL", tax_id: "RO12345678", county: "Cluj", city: "Cluj-Napoca", country: "RO" },
lines: [{ description: "Abonament SaaS", quantity: 1, unit_price: 400, vat_rate: 21 }],
currency: "RON",
metadata: { order_id: String(orderId) },
}),
}).then((r) => r.json());
console.log(invoice.number, invoice.totals); // "FCT-000123" { net, vat, gross }python
import os, uuid, requests
BASE = "https://api.4invoices.net/v1"
token = requests.post(f"{BASE}/auth/token", json={
"grant_type": "client_credentials",
"client_id": os.environ["FOURINVOICES_CLIENT_ID"],
"client_secret": os.environ["FOURINVOICES_CLIENT_SECRET"],
}, timeout=30).json()["access_token"]
headers = {
"Authorization": f"Bearer {token}",
# Uma chave por operação LÓGICA — reutilize-a na nova tentativa, nunca a gere de novo.
"Idempotency-Key": f"order-{order_id}-invoice",
}
invoice = requests.post(f"{BASE}/invoices", headers=headers, json={
"buyer": {"name": "Exemplu Comert SRL", "tax_id": "RO12345678",
"county": "Cluj", "city": "Cluj-Napoca", "country": "RO"},
"lines": [{"description": "Abonament SaaS", "quantity": 1,
"unit_price": 400, "vat_rate": 21}], # percentagem, não 0.21
"currency": "RON",
}, timeout=60).json()
print(invoice["number"], invoice["totals"])Autenticação
- O fluxo é client_credentials: troca client_id + client_secret por um access_token do tipo Bearer.
- O token expira em 3600 segundos. Renove-o antes de expirar, não em cada chamada — POST /auth/token tem o seu próprio limite de pedidos por IP.
- O client_secret é guardado apenas como hash e não pode ser recuperado. Se o perder, cria uma nova credencial e revoga a antiga.
- Apenas servidor a servidor. O CORS não permite nenhuma origem de browser: a partir do JavaScript de uma página, o segredo ficaria exposto ao visitante.
- Os scopes são atribuídos por credencial. Emita uma credencial separada para cada sistema e atribua a cada uma apenas os scopes mínimos de que precisa.
Faturamento → Definições → Acesso à API
bash
curl -sS -X POST https://api.4invoices.net/v1/auth/token \
-H 'Content-Type: application/json' \
-d '{
"grant_type": "client_credentials",
"client_id": "cli_XXXXXXXXXXXX",
"client_secret": "sec_XXXXXXXXXXXXXXXXXXXX"
}'
# → {"access_token":"eyJ...","token_type":"Bearer","expires_in":3600,
# "scope":"invoices:read invoices:write efactura:submit"}javascript
// Guarde o token em cache; não gere um por pedido.
let cached = { token: "", expiresAt: 0 };
async function getToken() {
if (cached.token && Date.now() < cached.expiresAt - 60_000) return cached.token;
const res = await fetch("https://api.4invoices.net/v1/auth/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
grant_type: "client_credentials",
client_id: process.env.FOURINVOICES_CLIENT_ID,
client_secret: process.env.FOURINVOICES_CLIENT_SECRET,
}),
});
if (!res.ok) throw new Error(`token ${res.status}`);
const data = await res.json();
cached = { token: data.access_token, expiresAt: Date.now() + data.expires_in * 1000 };
return cached.token;
}As alíquotas de impostos são percentagens
vat_rate: 21 ✓ · vat_rate: 0.19 ✗ · vat_rate: 1 ✗- vat_rate é uma PERCENTAGEM: 21 significa 21%.
- Os valores em (0, 1] são rejeitados — 0.19 é uma fração, e 1 é ambíguo entre 1% e 100%.
- 0 é válido e significa isenção ou autoliquidação; coloque a menção legal em notes.
- unit_price é o preço unitário LÍQUIDO quando o emitente é sujeito passivo de impostos.
- Precisa dos totais antes de confirmar? POST /v1/invoices/preview-totals executa o mesmo cálculo sem consumir um número fiscal.
Idempotência nas escritas fiscais
- O cabeçalho Idempotency-Key é OBRIGATÓRIO em POST /invoices, POST /invoices/{id}/storno e POST /invoices/{id}/efactura/submit.
- As chaves são memorizadas durante 24 horas. Repetir a mesma chave com o mesmo corpo devolve o resultado original e define Idempotency-Replayed: true.
- A mesma chave com um corpo diferente devolve 409 idempotency_key_reuse — um documento fiscal já emitido nunca é substituído.
- Uma chave por operação LÓGICA, não por tentativa HTTP: order-10457-invoice, não um UUID novo em cada nova tentativa.
- O motivo é legal, não técnico: um número fiscal consumido e uma fatura submetida no sistema nacional de faturamento eletrônico não podem ser retirados.
bash
curl -sS -X POST https://api.4invoices.net/v1/invoices \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: order-10457-invoice' \
-d '{
"buyer": {
"name": "Exemplu Comert SRL",
"tax_id": "RO12345678",
"address": "Str. Fabricii 12",
"city": "Cluj-Napoca",
"county": "Cluj",
"country": "RO",
"email": "[email protected]"
},
"lines": [
{ "description": "Abonament SaaS, iulie", "quantity": 1, "unit_price": 400, "vat_rate": 21, "unit": "buc" },
{ "description": "Implementare", "quantity": 6, "unit_price": 250, "vat_rate": 21, "unit": "ora" }
],
"currency": "RON",
"document_kind": "factura",
"due_date": "2026-08-15",
"metadata": { "order_id": "10457" }
}'Todos os endpoints
| Método | Endpoint | Scope | Idempotency-Key | Pedidos / minuto |
|---|---|---|---|---|
| POST | /auth/token Trocar as credenciais por um token de acesso | — | — | 120 |
| GET | /me Tenant, scopes e limites atuais | invoices:read | — | 120 |
| POST | /invoices Emitir uma fatura ou proforma | invoices:write | obrigatório | 30 |
| GET | /invoices Listar faturas (paginação por cursor) | invoices:read | — | 120 |
| POST | /invoices/preview-totals Calcular totais sem criar nada | invoices:read | — | 120 |
| GET | /invoices/{invoice_id} Obter uma fatura | invoices:read | — | 120 |
| GET | /invoices/{invoice_id}/pdf Descarregar o PDF da fatura | invoices:read | — | 120 |
| GET | /invoices/{invoice_id}/xml Descarregar o XML UBL / CIUS-RO (Roménia) | invoices:read | — | 120 |
| POST | /invoices/{invoice_id}/storno Emitir uma nota de crédito que anula esta fatura | invoices:write | obrigatório | 30 |
| POST | /invoices/{invoice_id}/payments Marcar a fatura como paga | invoices:write | — | 30 |
| DELETE | /invoices/{invoice_id}/payments Marcar a fatura como não paga | invoices:write | — | 30 |
| GET | /clients Listar clientes | clients:read | — | 120 |
| POST | /clients Criar ou atualizar um cliente | clients:write | — | 30 |
| GET | /lookup/company/{tax_id} Validar um CUI romeno no registro da ANAF | clients:read | — | 120 |
| GET | /series Listar as séries de numeração | invoices:read | — | 120 |
| POST | /invoices/{invoice_id}/efactura/validate Pré-verificação CIUS-RO (Roménia) — validar sem enviar | efactura:read | — | 120 |
| POST | /invoices/{invoice_id}/efactura/submit Enviar a fatura para a ANAF (SPV, Roménia) | efactura:submit | obrigatório | 10 |
| GET | /efactura/submissions Listar os envios para a ANAF (Roménia) | efactura:read | — | 120 |
| GET | /efactura/submissions/{submission_id} Obter um envio | efactura:read | — | 120 |
| POST | /efactura/submissions/{submission_id}/refresh Consultar a ANAF (Roménia) sobre o estado atual | efactura:read | — | 10 |
| GET | /efactura/submissions/{submission_id}/download Descarregar o arquivo da resposta assinada | efactura:read | — | 120 |
| GET | /efactura/inbox Faturas de fornecedores recebidas através do SPV (Roménia) | efactura:read | — | 120 |
| GET | /efactura/inbox/{inbound_id} Obter uma fatura recebida | efactura:read | — | 120 |
| GET | /efactura/inbox/{inbound_id}/download Descarregar o arquivo da fatura recebida | efactura:read | — | 120 |
| POST | /efactura/inbox/sync Obter as novas mensagens do SPV (ANAF, Roménia) para a caixa de entrada | efactura:read | — | 10 |
25 endpoints · https://api.4invoices.net/v1/openapi.json
Scopes
- invoices:read
- invoices:write
- clients:read
- clients:write
- efactura:read
- efactura:submit
O circuito ANAF e-Factura (Roménia)
- O verdadeiro fator diferenciador: para a Roménia, todo o ciclo da e-Factura com a ANAF decorre através da API, e não apenas a geração do documento.
- POST /invoices/{id}/efactura/validate executa, para o mercado romeno, a validação prévia CIUS-RO e devolve exatamente os campos que a ANAF rejeitaria, sem enviar nada.
- GET /invoices/{id}/xml gera o XML UBL / CIUS-RO (o perfil romeno) sem o submeter — útil para o seu próprio arquivo ou para uma auditoria interna.
- POST /invoices/{id}/efactura/submit submete-a no SPV (ANAF, Roménia). É irreversível: uma segunda cópia da mesma fatura não pode ser retirada do SPV romeno.
- O ciclo de vida está normalizado: not_sent → validating → queued → sent → processing → accepted | rejected | error. accepted significa transmitida legalmente; error é uma falha de transporte do nosso lado e pode ser repetida em segurança.
- GET /efactura/submissions/{id}/download obtém, para o mercado romeno, o arquivo com a resposta assinada da ANAF.
- O lado da receção também existe: POST /efactura/inbox/sync obtém as novas mensagens do SPV (ANAF, Roménia) e GET /efactura/inbox lista as faturas que os seus fornecedores lhe enviaram.
bash
# CIUS-RO preflight. Sends NOTHING to ANAF.
curl -sS -X POST "https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/validate?include_xml=true" \
-H "Authorization: Bearer $ACCESS_TOKEN"
# → {"invoice_id":"inv_01J7ABC","valid":false,
# "errors":["buyer.county is required for RO buyers"],
# "xml_base64":"PD94bWwg..."}bash
curl -sS -X POST https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/submit \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Idempotency-Key: efactura-inv_01J7ABC-1'
# → {"submission_id":"sub_01J7XYZ","status":"queued"}python
import time, requests
BASE = "https://api.4invoices.net/v1"
TERMINAL = {"accepted", "rejected"}
H = {"Authorization": f"Bearer {token}"}
def wait_for_anaf(submission_id, timeout=900):
deadline = time.time() + timeout
delay = 15
while time.time() < deadline:
r = requests.get(f"{BASE}/efactura/submissions/{submission_id}", headers=H, timeout=30)
r.raise_for_status()
status = r.json()["status"]
if status in TERMINAL:
return r.json()
# /refresh asks ANAF directly and shares the 10/min submit bucket.
requests.post(f"{BASE}/efactura/submissions/{submission_id}/refresh", headers=H, timeout=30)
time.sleep(delay)
delay = min(delay * 2, 120)
raise TimeoutError(submission_id)Erros
- Todos os 4xx e 5xx usam o mesmo envelope: { "error": { type, code, message, param?, doc_url, request_id, errors? } }.
- type é a classe geral com base na qual decide o fluxo («posso tentar de novo?»), e code é o motivo estável que mapeia no seu próprio sistema.
- param é o caminho, com pontos, do campo em causa, por exemplo lines.0.vat_rate.
- errors[] aparece quando um único pedido tem problemas em mais de um campo.
- request_id fica registado do nosso lado. Indique-o em qualquer pedido de suporte — identifica o pedido exato.
- Também é devolvido um 404 para um id que pertence a outro tenant: nunca confirmamos a existência de dados de terceiros.
json
{
"error": {
"type": "invalid_request_error",
"code": "validation_failed",
"message": "Datele trimise nu sunt valide.",
"param": "lines.0.vat_rate",
"doc_url": "https://4invoices.net/ro/api-dezvoltatori#errors",
"request_id": "req_8a893f2f33d4472da8d6e144",
"errors": [
{ "param": "lines.0.vat_rate", "message": "VAT rate must be a percent (21), not a fraction", "type": "value_error" }
]
}
}| Estado | Tipo | Código |
|---|---|---|
| 401 | authentication_error | missing_bearer_token |
| 401 | authentication_error | invalid_client |
| 401 | authentication_error | token_expired |
| 401 | authentication_error | invalid_token |
| 401 | authentication_error | unauthorized |
| 403 | permission_error | insufficient_scope |
| 403 | permission_error | forbidden |
| 404 | not_found_error | not_found |
| 409 | conflict_error | idempotency_key_reuse |
| 409 | conflict_error | idempotency_in_progress |
| 409 | conflict_error | no_series_configured |
| 422 | invalid_request_error | validation_failed |
| 422 | invalid_request_error | issuer_profile_incomplete |
| 422 | invalid_request_error | cius_ro_incomplete |
| 422 | invalid_request_error | cannot_storno_draft |
| 422 | invalid_request_error | nothing_to_storno |
| 422 | invalid_request_error | invalid_json_number |
| 429 | rate_limit_error | rate_limit_exceeded |
| 502 | upstream_error | upstream_error |
| 503 | service_unavailable_error | service_unavailable |
Limites de pedidos
| Bucket | Pedidos / minuto | O que significa |
|---|---|---|
| read | 120 | GET *, POST /invoices/preview-totals, POST /invoices/{id}/efactura/validate |
| write | 30 | POST /invoices, POST /invoices/{id}/storno, POST|DELETE /invoices/{id}/payments, POST /clients |
| submit | 10 | POST /invoices/{id}/efactura/submit, POST /efactura/submissions/{id}/refresh, POST /efactura/inbox/sync |
- Os limites são por credencial e por minuto: 120 para leituras, 30 para escritas e 10 para as operações de faturamento eletrônico (submit, refresh, inbox/sync).
- X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset aparecem em TODAS as respostas, incluindo a 429.
- Um 429 inclui também Retry-After em segundos. Respeite-o; não repita pedidos num ciclo apertado.
- O limite de 10/min existe porque, na Roménia, a própria ANAF permite aproximadamente uma chamada de listagem de mensagens por minuto e por CIF.
- Coloque /efactura/inbox/sync num cron, não numa consulta periódica agressiva.
- Precisa de limites mais elevados? Peça-os através do Contato, indicando o volume diário previsto.
X-RateLimit-Limit · X-RateLimit-Remaining · X-RateLimit-Reset · Retry-After
http
HTTP/2 429
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1785312000
Retry-After: 17
Content-Type: application/json
{"error":{"type":"rate_limit_error","code":"rate_limit_exceeded",
"message":"...","doc_url":"https://4invoices.net/ro/api-dezvoltatori#errors",
"request_id":"req_..."}}javascript
// Respeite o Retry-After; nunca repita um 4xx que não seja 429.
async function call(url, init, attempt = 0) {
const res = await fetch(url, init);
if (res.status === 429 || res.status >= 500) {
if (attempt >= 5) return res;
const retryAfter = Number(res.headers.get("Retry-After")) || 2 ** attempt;
await new Promise((r) => setTimeout(r, retryAfter * 1000));
return call(url, init, attempt + 1);
}
return res;
}
// Uma nova tentativa de escrita TEM de reutilizar o MESMO Idempotency-Key, senão emite
// um segundo documento fiscal.Guias por tema
Cada tema tem a sua página, com os endpoints, exemplos e erros respetivos.
- Autenticação na API 4invoicesTroque client_id e client_secret por um token Bearer válido uma hora, apenas servidor a servidor.
- Emitir faturas pela APIPOST /invoices com Idempotency-Key, impostos em percentagem, mais listagem, nota de crédito e marcar como paga.
- Clientes e consulta ao registro da ANAF (Roménia)Uma inserção ou atualização deduplicada por tax_id e uma consulta ao registro da ANAF para empresas romenas, para que a e-Factura não seja rejeitada.
- e-Factura da ANAF (Roménia) pela APIPara a Roménia: pré-validação CIUS-RO, submissão ao SPV, estado normalizado, resposta assinada e caixa de faturas recebidas.
- Séries de numeração na APISem uma série ativa do tipo fiscale, a emissão devolve 409 no_series_configured.
- Códigos de erro e o envelope de erroUm único formato em todas as rotas: type, code, message, param, doc_url, request_id e errors.
- Limites de pedidos e retentativas120 leituras, 30 escritas e 10 operações de faturamento eletrônico por minuto e credencial, com cabeçalhos X-RateLimit-*.
Erros frequentes
- Enviar os impostos como fração (0.19) ou como 1. Ambos são rejeitados; envie 19 ou 21.
- Criar um token por pedido. O token dura uma hora; guarde-o em cache ou irá atingir o limite por IP do endpoint de tokens.
- Gerar uma nova chave de idempotência em cada nova tentativa — precisamente o cenário que produz faturas duplicadas.
- Chamar a API a partir de JavaScript no browser. O CORS bloqueia todas as origens e, de qualquer forma, o segredo ficaria exposto.
- Submeter no sistema nacional de faturamento eletrônico sem a validação prévia (CIUS-RO na Roménia). Uma submissão errada não pode ser retirada.
- Consultar /efactura/submissions/{id}/refresh mais de 10 vezes por minuto — esse limite é partilhado com submit.
- Emitir antes de o perfil da empresa estar completo e de existir uma série fiscal ativa.
Perguntas e respostas para desenvolvedores
Como obtenho credenciais para a API 4invoices?
No painel, em Faturamento → Definições → Acesso à API. Recebe um client_id e um client_secret; o secret é mostrado uma única vez e guardado apenas como hash.
Quanto tempo dura o access_token?
3600 segundos, ou seja uma hora. Guarde-o em cache e renove antes de expirar — o endpoint de token tem limite próprio por IP.
Como envio a alíquota de imposto?
Como percentagem: 21 para 21%. Os valores em (0, 1] são rejeitados, logo 0.19 e 1 falham a validação.
Que chamadas exigem Idempotency-Key?
POST /invoices, POST /invoices/{id}/storno e POST /invoices/{id}/efactura/submit. As chaves são recordadas 24 horas e uma repetição devolve o documento original com Idempotency-Replayed: true.
Posso submeter uma fatura à e-Factura da ANAF (Roménia) diretamente pela API?
Sim, para o mercado romeno: pré-validação CIUS-RO com /efactura/validate, submissão com /efactura/submit, acompanhamento do estado normalizado em /efactura/submissions/{id} e download da resposta assinada pela ANAF.
Quais são os limites de pedidos?
Por credencial, por minuto: 120 leituras, 30 escritas e 10 operações de faturamento eletrônico. Cada resposta traz cabeçalhos X-RateLimit-*, e um 429 acrescenta Retry-After.
Posso chamar a API do frontend?
Não. É exclusivamente servidor a servidor: nenhuma origem de browser passa o CORS e um client_secret não deve estar em código que chega ao visitante.
Porque recebo issuer_profile_incomplete na primeira fatura?
O perfil da empresa está incompleto ou não existe uma série ativa do tipo fiscale. Complete ambos no painel; a API recusa produzir um documento fiscal inválido.