Why We Built an API for Spanish Fiscal ID Validation Instead of Just Implementing It
Source: Dev.to
Introduction
A few months ago I was integrating fiscal identifier validation into a project. I found a 30‑line JavaScript function, copied it, tested it with four cases, and it worked. I dropped it into the codebase and forgot about it.
Three months later, a user emailed us: their CIF wasn’t validating. It was a perfectly valid CIF. That’s when I realized there’s a difference between implementing validation and maintaining it correctly.
Common Pitfalls in Spanish Fiscal Identifier Validation
NIF
The basic algorithm (8 digits + 1 letter, modulo 23) looks simple, but there are special formats—K, L and M NIFs for specific cases—that most implementations simply ignore.
NIE
A NIE starts with X, Y or Z, then follows the NIF algorithm with a substitution. Many regexes you’ll find online accept 7 or 8 digits interchangeably, while the correct format depends on the prefix.
CIF
This is where almost everything breaks:
- The control character can be a letter or a digit depending on the entity type (the first letter of the CIF).
- Most implementations accept either for all types, which is incorrect.
- When
(10 - sum % 10) % 10 === 0, the control character should be J in certain cases—an edge case that produces silent bugs that are extremely hard to track down.
IBAN
The MOD‑97 algorithm requires arithmetic with very large numbers. In JavaScript you need BigInt, and in environments where it’s unavailable or poorly implemented, the validation fails without a visible error.
The Maintenance Problem
None of these bugs surface in development; they appear in production with real identifiers from real users.
When a validation fails visibly—throws an exception or returns an error—you catch it and fix it. The real problem with fiscal‑validation bugs is that they accept invalid identifiers without warning. A user enters a CIF with an incorrect control digit, your code says “valid”, the data is stored, and months later the problem surfaces during a fiscal operation—by then you have no idea where the bad data came from.
Even if you implement everything correctly today, the rules can change. Spain has updated fiscal‑identifier formats in the past; NIE formats have evolved. When that happens, someone has to update the code, and that person might not be the original author, might be on a different team, or simply might not remember why each decision was made.
Why an API Helps
With an API, the maintenance burden shifts to the API maintainer. You consume a stable endpoint, and they keep the algorithms up to date.
We built Valix—a REST API that validates NIF, NIE, CIF and IBAN using the official Spanish algorithms, with automatic type detection and a structured JSON response.
Valix API Example (Python)
import requests
response = requests.post(
"https://api.getvalix.io/v1/validate/trial",
json={
"items": [
{"value": "12345678Z", "type": "AUTO"},
{"value": "X1234567L", "type": "AUTO"},
{"value": "A12345674", "type": "AUTO"},
{"value": "ES9121000418450200051332", "type": "AUTO"}
]
}
)
result = response.json()
for item in result["results"]:
status = "valid" if item["valid"] else f"invalid: {', '.join(item['errors'])}"
print(f"{item['value']} → {item['detected_type']} — {status}")Output
12345678Z → NIF — valid
X1234567L → NIE — valid
A12345674 → CIF — valid
ES9121000418450200051332 → IBAN — validThe trial endpoint requires no registration or API key—50 validations per day per IP, so you can test it before committing to anything.
When to Use an Internal Implementation
If your validation volume is very low, you’re always validating the same identifier type, and you have exhaustive tests with real‑world cases, implementing it internally can make sense.
However, if you’re validating identifiers from production users, mixing types (NIF + NIE + CIF + IBAN), or simply don’t want to spend time maintaining this logic, an API is the more sensible choice.
Resources
- API and documentation:
- Code examples (Python, JavaScript, PHP, cURL):
- JavaScript/TypeScript SDK:
npm i @valix/sdk
Disclaimer
I’m the author of Valix.