← Documentacao / Guias
Convenções da API
Estrutura de pedidos, âmbitos de autenticação, consultas de listagem, valores monetários, erros, idempotência e limites de caudal.
Estrutura de pedidos
Todas as operações são do tipo RPC através de POST:
POST /v1/{module}/{resource}/{action}
Módulos: reference, partners, catalog, sales, purchases, ledger, bank, declarations, files, webhooks, audit. As ações são verbos: create, get, update, delete, list, além de ações de domínio como issue, register, match, apply-advance, generate.
Autenticação e âmbitos (scopes)
Authorization: Bearer <api key>. As chaves contêm âmbitos validados por ação:
{module}:read- ações de obtenção e listagem (get/list){module}:write- operações de alteração (mutations){module}:*ou*- carateres universal (wildcards)
Ámbito em falta → 403 forbidden. Chave em falta ou inválida → 401 unauthorized.
Consultas de listagem
Todas as ações list partilham o mesmo contrato:
{
"page": 1,
"pageSize": 50,
"sort": [{ "field": "createdAt", "dir": "desc" }],
"filter": [{ "field": "paymentStatus", "op": "eq", "value": "unpaid" }]
}
Operadores de filtro: eq (igual), ne (diferente), contains (correspondência de texto insensível a maiúsculas/minúsculas, apenas para campos de texto), gte (maior ou igual que), lte (menor ou igual que), in (qualquer valor de uma lista até 500 elementos). Os campos ordenáveis e filtráveis estão definidos numa lista branca por ponto de final endpoint (consulte a especificação OpenAPI); os campos desconhecidos devolvem o código 400. Adicione totals: ["field", …] ao pedido para somar campos numéricos em todas as linhas correspondentes; quando os registos contêm uma moeda, totalsByCurrency apresenta essas mesmas somas divididas por código de moeda. Respostas: { rows, total, page, pageSize, totals?, totalsByCurrency? }.
Valores monetários e datas
Os valores monetários são strings decimais com um máximo de 4 casas decimais ("121.0000") - nunca números de vírgula flutuante (floats). O IVA é calculado linha a linha com arredondamento comercial (meio para cima, ou half-up). As datas seguem o formato YYYY-MM-DD; os carateres de fecho temporal (timestamps) utilizam o formato ISO 8601 em UTC.
Erros
Existe um únicoinvólucro (envelope) para todas as respostas de erro:
{
"error": {
"code": "validation",
"message": "Request validation failed",
"requestId": "k1x…",
"key": "request_invalid",
"fieldErrors": { "lines.0.unitPriceExclVat": ["Invalid value"] }
}
}
Códigos: validation (400/422, e 413 se um ficheiro carregado ou o corpo do pedido forem demasiado grandes), unauthorized (401), payment_required (402, o período de avaliação ou o crédito pré-pago terminaram; a mensagem indica como proceder), forbidden (403), not_found (404), conflict (409), idempotency_key_reuse (422), idempotency_in_progress (409), rate_limited (429), internal (5xx). Quando a mensagem corresponde a uma mensagem fixa, o campo key identifica-a para que o cliente possa apresentar a sua própria tradução, enquanto o campo params contém os respetivos valores (por exemplo, { "period": "2026-09" } para um período contabilístico encerrado). Inclua o requestId ao comunicar problemas.
Idempotência
Adicione Idempotency-Key: <qualquer string com ≤255 carateres> a qualquer operação de modificação:
- Repetir com a mesma chave e a mesma carga útil (payload) → a resposta armazenada é reproduzida byte a byte com o cabeçalho
x-idempotent-replay: true. - Mesma chave, carga útil diferente → 422
idempotency_key_reuse. - Pedido duplicado simultâneo enquanto o primeiro ainda está a ser processado → 409
idempotency_in_progress. - As chaves pertencem à chave de API ou ao utilizador que as envia, dentro da empresa em cujo nome a chamada é efetuada, permitindo que duas integrações da mesma empresa utilizem a mesma chave. As chamadas efetuadas antes de a empresa existir e as chamadas
account/*mantêm as chaves por utilizador, pelo que uma chamada repetida aaccount/companies/createcria apenas uma empresa. - Uma resposta armazenada só é devolvida depois de o chamador passar novamente pelas mesmas validações de permissões (ámbitos, função, empresa e estado de faturação); caso contrário, a chamada obtém o erro atual.
- As chaves expiram após 24 horas. As respostas de erro (4xx) também são reproduzidas; as respostas 5xx não são armazenadas, pelo que as tentativas são executadas novamente.
Limites de caudal (rate limits)
300 pedidos por minuto por chave de API (por credencial apresentada; os pedidos não autenticados têm limites aplicados por IP). Em caso de erro 429, respeite o cabeçalho retry-after. Os cabeçalhos x-ratelimit-* indicam o seu orçamento disponível.
Webhooks
Os eventos são gravados numa tabela de transações (transactional outbox) na mesma transação de base de dados da alteração - um documento revertido nunca emite um evento e nenhum evento é perdido. Entregas:
- Um pedido
POSTpara o seu URL com o JSON do evento x-nordlet-timestamp: <segundos unix>, o momento em que a entrega foi assinadax-nordlet-signature-v2: t=<timestamp>,v1=<hex HMAC-SHA256 de "<timestamp>.<raw body>">utilizando o seu segredo de subscriçãox-nordlet-signature: sha256=<hex HMAC-SHA256 of the raw body>, mantido inalterado para recetores existentesx-nordlet-deliverycontém o identificador da entrega, que se mantém igual em todas as tentativas de uma mesma entrega- Uma resposta sem o código 2xx ou um redirecionamento motivam uma nova tentativa após 30 segundos, 2 minutos, 10 minutos, 30 minutos, 1 hora, 3 horas, 6 horas e 12 horas, num total aproximado de 24 horas, antes de a entrega ser marcada como falhada
- Cada entrega é enviada por um único servidor de cada vez, pelo que a execução de várias instâncias da API não resulta em envios duplicados
Valide o cabeçalho x-nordlet-signature-v2 utilizando uma comparação de tempo constante antes de confiar na carga útil (payload) e rejeite entregas cuja marca temporal difira do seu relógio em mais de 5 minutos. A marca temporal faz parte do texto assinado, impedindo que uma entrega intercetada seja reutilizada mais tarde com uma nova marca temporal. Armazene os identificadores x-nordlet-delivery já processados para ignorar repetições dentro dessa janela temporal. Uma entrega falhada pode ser reenviada através de webhooks/deliveries/redeliver.
Auditoria
Todas as alterações são registadas (actor, action, entity, diff) e podem ser consultadas através de audit/list.
Garantias contabilísticas
- Os lançamentos em diário são sempre equilibrados - isto é garantido por um gatilho (trigger) diferido na base de dados no momento da gravação, e não apenas pelo código da aplicação.
- A numeração de documentos é contínua e sem saltos por série/ano; a atribuição é segura face à concorrência.
- Os períodos contabilísticos bloqueados rejeitam qualquer lançamento com data no seu interior (código 409).
- Os documentos eliminados logicamente (soft-deleted) mantêm o respetivo rasto de auditoria; os documentos emitidos ou registados não podem ser eliminados.