Every electronic invoice submitted to Colombia’s DIAN must be digitally signed using a PFX (PKCS#12) certificate issued through the DIAN habilitación process. DIAN REST API reads this certificate at application startup via theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/farojas85/fast-rest-api/llms.txt
Use this file to discover all available pages before exploring further.
Settings class and refuses to start if the file cannot be found, decrypted, or parsed. This fast-fail design prevents silent signing failures from reaching production traffic.
What Is a PFX Certificate?
A.pfx file (also called a PKCS#12 archive) bundles three pieces of cryptographic material into a single, password-protected binary file:
- Private key — used to create the digital signature on each XML invoice.
- Public certificate — contains the signer’s identity and is included in the signed envelope.
- Chain certificates (optional) — intermediate CA certificates that establish trust back to the root.
vpfe-hab environment.
Obtaining Your Certificate
Complete DIAN software registration
Log in to the DIAN portal and complete the Registro de Software process for your billing software. You will need your NIT, software name, and technical contact information.
Download the .pfx file
After approval, the DIAN portal provides a downloadable
.pfx file. Store it securely — this file cannot be regenerated without re-registering.Placing the Certificate
DIAN_CERT_PATH must be an absolute path on the server where the API process runs. Do not use relative paths; Pydantic’s FilePath type resolves paths relative to the process working directory, which can differ between deployment environments.
The recommended directory layout keeps certificates isolated under a dedicated system directory:
Configuring the Environment
Add the following two variables to your.env file (or inject them via your secrets manager / container orchestrator):
Settings is:
Startup Validation
Settings uses a Pydantic @model_validator(mode="after") to verify the certificate immediately when the application process starts. The validator opens the file and passes the raw bytes through pkcs12.load_key_and_certificates() from the cryptography library. If any step fails the application raises a ValueError and exits before accepting any HTTP traffic.
Here is the exact validator from src/infrastructure/config/settings.py:
DIAN_CERT_PASSWORDis declared asSecretStr, so Pydantic never prints its value in logs or tracebacks. The validator calls.get_secret_value()only at the point of use.DIAN_CERT_PATHis declared asFilePath, which means Pydantic itself validates that the path exists before the model validator even runs. If the file is missing you receive aValidationErrorfrom Pydantic, not aValueErrorfrom the validator.
Common Certificate Errors
ValidationError: DIAN_CERT_PATH is not a valid path
ValidationError: DIAN_CERT_PATH is not a valid path
Pydantic’s
FilePath type requires the file to exist on disk at the moment Settings() is instantiated. This error fires before the PFX validator runs.Fix: Confirm the absolute path is correct and that the file exists at that exact location. Check for typos, trailing spaces, or environment variable interpolation issues. Run ls -la /etc/dian-api/certificates/ to verify.ValueError: Failed to load the PFX certificate
ValueError: Failed to load the PFX certificate
The file exists and is readable, but
pkcs12.load_key_and_certificates() raised an exception. The three most common causes are:- Wrong password — double-check
DIAN_CERT_PASSWORD. Passwords are case-sensitive and may contain special characters that need escaping in.envfiles (wrap the value in double quotes if it contains#,=, or spaces). - Corrupted file — re-download the
.pfxfrom the DIAN portal and replace the existing file. - Wrong file format — the file must be a PKCS#12 archive (
.pfxor.p12). A PEM-encoded.crtor.pemfile will not work.
FileNotFoundError during startup (OS-level)
FileNotFoundError during startup (OS-level)
If the process user does not have read permission on the
.pfx file, the open() call inside the validator raises FileNotFoundError or PermissionError, which is then wrapped in the ValueError.Fix: Ensure the file has at least 600 permissions and is owned by the user that runs the API process: