GOBL ➡️ Portugal SAF-T

June 26, 2026 · View on GitHub

Portuguese SAF-T (PT) tax addon for GOBL.

Released under the Apache 2.0 LICENSE, Copyright 2026 Invopop S.L..

Lint Test Go Go Report Card codecov GoDoc Latest Tag Ask DeepWiki

Portugal doesn't have an e-invoicing format per se. Tax information is reported electronically to the AT (Autoridade Tributária e Aduaneira) either periodically in batches via a SAF-T (PT) report or individually in real time via a web service. This addon (pt-saft-v1) ensures that GOBL documents carry all the fields the AT requires.

Unlike the format converters in the GOBL ecosystem, this is a true addon: it registers extensions, normalizers, scenarios, and validation rules into GOBL's global registry. It lives in its own module so that only projects handling Portuguese SAF-T documents take on its weight.

Layout

  • addon/ — the GOBL addon: extensions, normalizers, scenarios, and validation rules that register into GOBL on import. This package is kept dependency-light so importing it never pulls in conversion tooling.
  • the module root (and future subpackages) is reserved for converters and other SAF-T logic that build on the addon.

Usage

Add a blank import of the addon so it registers itself, then use GOBL as normal:

import (
	"github.com/invopop/gobl"
	_ "github.com/invopop/gobl.pt.saft/addon"
)

Declare the addon on a document (or let the regime/scenario add it) and Calculate + Validate will run the full SAF-T normalization and rules.

Note: the pt-saft-v1 key is listed in GOBL core's approved external-addon registry, so it is recognised as a valid $addons value in the JSON Schema. The runtime check stays strict, however: a document declaring the pt-saft-v1 addon will fail validation with add-on must be registered unless this module is imported. Any service that processes Portuguese SAF-T documents must import it.

Development

The addon builds on core GOBL features (the approved external-addon registry) that are not yet in a tagged release. The go.mod therefore pins github.com/invopop/gobl to the core checkout via a replace directive; bump it to the release tag and drop the replace once core is published.

go test ./...

Examples

examples/ holds sample documents, with their expected JSON envelopes under examples/out/. They are verified via GOBL's shared pkg/examples helpers. Regenerate the golden output after intentional changes with:

go test . -run TestExamples -update

License

Apache 2.0 — see LICENSE.