Why We Built an API for Spanish Fiscal ID Validation Instead of Just Implementing It

Published: (April 1, 2026 at 11:35 AM EDT)
4 min read
Source: Dev.to

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 — valid

The 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.

0 views
Back to Blog

Related posts

Read more »