Reference

Every identifier, and the check behind it

A shape is not evidence. Nine digits describes a bank account and equally well an invoice number, a policy number and a customer ID — so what separates a detection you can act on from a guess that destroys a document is whether there is a checksum underneath it. This is the full list, with the check each one gets.

Talk to our technical team → — or read the live list, unauthenticated, at GET /api/v1/pii-types.

Indian identifiers

On by default, because every one of these is either checksum-validated or structurally distinctive enough to be safe on a document nobody has classified.

TypeShapeCheckDefault
aadhaar12 digitsVerhoeff check digit. A twelve-digit run that fails it is a misread, not a number.on
vid16 digitsVirtual ID. Rejected if the first twelve form a valid Aadhaar, since that is an Aadhaar number plus four digits.on
panAAAAA9999AStructural. The fourth character encodes holder type and is reported, never enforced.on
passportA9999999Indian format. One letter, seven digits, excluding Q, X and Z.on
voter_epicAAA9999999Structural.on
driving_licenceState + RTO + 11 digitsStructural.on
gstin15 charactersEmbeds a PAN, which is what makes it distinctive.on
ifscAAAA0BBBBBBThe zero in position five is fixed.on
phone_in[6-9] + 9 digitsOptional +91. Indian mobile series only.on
bank_account9–18 digitsNone. See the warning below.off

Identifiers outside India

Available and off by default. The default set is what runs on a document nobody has classified, and widening it would change what every existing integration redacts without anyone having asked — on a product where a wrong redaction cannot be undone. Enable them with types=global.

TypeShapeCheckDefault
ibanAA99 + 11–30ISO 13616 mod-97. Move the first four characters to the end, map letters to numbers, and the integer must be 1 mod 97 — a 1-in-97 chance of a random string passing. The strongest check here.off
credit_card13–19 digitsLuhn plus a real issuer prefix. Luhn alone passes one random string in ten, so both are required.off
eu_vatCountry + 8–12The two-letter country prefix is what makes it distinctive. Covers the EU, plus GB and XI.off
uk_ninoAA999999AImpossible prefixes excluded — BG, GB, NK, KN, TN, NT, ZZ — plus the letters that never appear. Without these it matches any two-letter reference code.off
phone_e164+ + 8–15 digitsThe leading + is doing the work. Without it this is any long number.off
us_ssn999-99-9999No checksum exists. Structural rules only: no 000, 666 or 9xx area, no 00 group, no 0000 serial.off
emailAnything address-shapedUniversal. On by default in both sets.on
Two types carry a warning, and it is the same warning. bank_account and us_ssn have no checksum and no distinguishing shape. Nine digits describes a social security number, an invoice number, a policy number and a customer ID equally well. Enabled on an unclassified document they will match all of them, and unlike a missed identifier a wrong redaction cannot be undone — it destroys the document you were trying to make shareable. Turn them on where you already know what you are processing, and nowhere else.

Groups

So you do not list six identifiers to get a sensible set for where you operate. Pass a group name to types; it expands to its members, and you can mix a group with individual types.

india

The current default set: Aadhaar, VID, PAN, passport, voter EPIC, driving licence, GSTIN, IFSC, Indian mobile and email. Named so it can be asked for explicitly rather than relied on implicitly.

global

Everything not tied to one country's document formats: IBAN, payment cards, EU and UK VAT, UK National Insurance, E.164 phone and email. Deliberately excludes us_ssn, for the same reason bank_account is excluded from the Indian defaults.

all

Every type this API knows, including the two that are unsafe on an unclassified document. For a caller who knows exactly what they are sending.

curl -X POST https://api.maskaadhaar.com/api/v1/redact-pii \
  -H "X-API-Key: $MASKAADHAAR_KEY" \
  -F "file=@invoice.pdf" \
  -F "types=global" \
  --output redacted.pdf

GET /api/v1/pii-types returns this table as JSON and needs no authentication, so you can read the current list — and the groups — before a key is issued, rather than trusting this page to stay in step.

Why a checksum decides what is safe

Detection on an unclassified document is not a search problem, it is a false-positive problem. A missed identifier leaves a document no worse than it arrived. A wrong one covers something that mattered, and nobody can put it back.

So the bar for being on by default is not “does this pattern usually mean that identifier”. It is: can a wrong match be ruled out?

Questions we get asked

Why does detecting an identifier need a checksum?

Because a shape alone is not evidence. Nine digits describes a bank account and also an invoice number, a policy number and a customer ID. A checksum turns a guess into a check: a twelve-digit run that fails the Verhoeff test is a misread, not an Aadhaar number, and a wrong redaction cannot be undone.

Why is Luhn not enough on its own for a payment card?

Luhn passes roughly one random digit string in ten, which is nowhere near safe on a document nobody has classified. It has to be combined with a real issuer prefix — a leading 4, 34, 37, 5x, 2x or 6x — before a 13-to-19 digit run can be treated as a card number.

Which identifiers are detected by default?

The Indian set: Aadhaar, VID, PAN, passport, voter EPIC, driving licence, GSTIN, IFSC, Indian mobile numbers and email addresses. Non-Indian identifiers are available but off by default, so an existing integration's behaviour never changes without being asked.

How do I detect IBANs and payment cards instead?

Pass types=global, which enables IBAN, payment cards, EU and UK VAT numbers, UK National Insurance numbers, E.164 phone numbers and email addresses. You can also name individual types, or mix a group with specific ones.

Why are some identifiers off by default?

Because they have no checksum and no distinguishing shape. A US social security number is nine digits and an Indian bank account is nine to eighteen, which describes a great many ordinary reference numbers. Detecting them on an unclassified document would destroy the documents it was meant to make shareable.

Related

Need an identifier that is not here?

Tell us which one and which document it is printed on. A type with a checksum behind it is usually a day's work; the constraint is knowing what a false positive would cost you.