Published check-digit algorithms: GS1 General Specifications, ISO/IEC 7064, ISO/IEC 7812-1, ISO 2108, ISO 3297, ISO 6166, ISO 10957, ISO 17442, ISO 3779 with 49 CFR 565.15, 3GPP TS 23.003, ANSI X9 and CMS — each cited per scheme
GET/api/check-digitsList the supported check-digit schemesReturns a list
One record per scheme with its algorithm, alphabet, length rules, applicability scope, error-detection limits and specification reference.
Case-insensitive filter: any substring of the scheme id or name, or the start of any word in the algorithm description (so 'luhn' also finds imei, npi and isin). No match returns an empty list plus a warning — never a substitute scheme.
searchstring
Case-insensitive filter: any substring of the scheme id or name, or the start of any word in the algorithm description (so 'luhn' also finds imei, npi and isin). No match returns an empty list plus a warning — never a substitute scheme.
allowed: 1 – 40
example: search=isbn
Universal parametersShared response and formatting options6
Parameter
Type
Default & allowed
Description
count
int
default: 20
allowed: 1 – 100
example: 3
Limit the number of returned records (1–100). Defaults to 20.
fields
list
example: scheme,name
Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
exclude
list
example: meaning
Return all fields except these (comma-separated).
format
enum
default: json
allowed: json | ndjson | csv
example: csv
Response format: json envelope, ndjson (one record per line) or csv.
pretty
boolean
default: false
example: true
Pretty-print the JSON response.
unwrap
boolean
default: false
example: true
Drop the envelope: return the raw array/object without data/meta wrapper.
countint
Limit the number of returned records (1–100). Defaults to 20.
default: 20
allowed: 1 – 100
example: count=3
fieldslist
Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
example: fields=scheme,name
excludelist
Return all fields except these (comma-separated).
example: exclude=meaning
formatenum
Response format: json envelope, ndjson (one record per line) or csv.
default: json
allowed: json | ndjson | csv
example: format=csv
prettyboolean
Pretty-print the JSON response.
default: false
example: pretty=true
unwrapboolean
Drop the envelope: return the raw array/object without data/meta wrapper.
default: false
example: unwrap=true
Response schemaFields returned in each record18
Field
Type
Description
Example
scheme
string
Scheme id used by the scheme parameter.
gtin13
name
string
Human name of the identifier scheme.
GTIN-13 (EAN-13)
algorithm
string
The check-character algorithm in one sentence.
GS1 modulo-10: weights 3 and 1 alternating from the right, subtracted from the next multiple of ten
alphabet
string
Characters allowed in the payload.
0-9
lengths
integer[]
Accepted total lengths including the check characters. Empty for variable-length schemes.
[13]
minLength
integer
Smallest accepted total length — the only length rule for variable-length schemes.
13
checkCharacters
integer
Number of check characters: 1 for most schemes, 2 for MOD 97-10 and LEI.
1
checkAlphabet
string
Characters the check position may hold.
0-9
checkPosition
string
Where the check characters sit in the identifier.
last character
scope
string
Where the scheme (and its check character) actually applies — regional limits are stated here.
Global GS1 key, printed as an EAN-13 symbol.
strictRulesnullable
string
What strict=true adds on /validate, or null when the alphabet, length and check character are the whole format.
null
detectsAllSingleCharacterErrors
boolean
Whether every single-character substitution changes the check character.
true
undetectedSubstitutionsnullable
string
Which single-character changes slip through, or null when none do.
null
detectsAllAdjacentTranspositions
boolean
Whether swapping any two adjacent characters changes the check character.
false
undetectedTranspositionsnullable
string
Which adjacent swaps slip through, or null when none do.
Swapping two adjacent digits whose values differ by five is undetected (05↔50, 16↔61, 27↔72, 38↔83, 49↔94). Every other adjacent transposition changes the check digit.
specification
string
The published specification this implementation follows.
GS1 General Specifications — check-digit calculation
specificationUrlnullable
string
Public page for the specification, or null when only a paywalled standard exists.
https://www.gs1.org/standards/barcodes/ean-upc
meaning
string
What a valid check character does and does not prove for this scheme.
A correct check digit means the digits are internally consistent. It does not mean the GTIN has been allocated to a company or assigned to a product — this endpoint queries no GS1 registry and holds no product catalogue.
schemestring
Scheme id used by the scheme parameter.
example: gtin13
namestring
Human name of the identifier scheme.
example: GTIN-13 (EAN-13)
algorithmstring
The check-character algorithm in one sentence.
example: GS1 modulo-10: weights 3 and 1 alternating from the right, subtracted from the next multiple of ten
alphabetstring
Characters allowed in the payload.
example: 0-9
lengthsinteger[]
Accepted total lengths including the check characters. Empty for variable-length schemes.
example: [13]
minLengthinteger
Smallest accepted total length — the only length rule for variable-length schemes.
example: 13
checkCharactersinteger
Number of check characters: 1 for most schemes, 2 for MOD 97-10 and LEI.
example: 1
checkAlphabetstring
Characters the check position may hold.
example: 0-9
checkPositionstring
Where the check characters sit in the identifier.
example: last character
scopestring
Where the scheme (and its check character) actually applies — regional limits are stated here.
example: Global GS1 key, printed as an EAN-13 symbol.
strictRulesstringnullable
What strict=true adds on /validate, or null when the alphabet, length and check character are the whole format.
example: null
detectsAllSingleCharacterErrorsboolean
Whether every single-character substitution changes the check character.
example: true
undetectedSubstitutionsstringnullable
Which single-character changes slip through, or null when none do.
example: null
detectsAllAdjacentTranspositionsboolean
Whether swapping any two adjacent characters changes the check character.
example: false
undetectedTranspositionsstringnullable
Which adjacent swaps slip through, or null when none do.
example: Swapping two adjacent digits whose values differ by five is undetected (05↔50, 16↔61, 27↔72, 38↔83, 49↔94). Every other adjacent transposition changes the check digit.
specificationstring
The published specification this implementation follows.
example: GS1 General Specifications — check-digit calculation
specificationUrlstringnullable
Public page for the specification, or null when only a paywalled standard exists.
What a valid check character does and does not prove for this scheme.
example: A correct check digit means the digits are internally consistent. It does not mean the GTIN has been allocated to a company or assigned to a product — this endpoint queries no GS1 registry and holds no product catalogue.
Documented examples
Build-generated requests and complete responses3
Every supported scheme /api/check-digits
GET /api/check-digits
{
"data": [
{
"scheme": "luhn",
"name": "Luhn (generic mod-10)",
"algorithm": "Luhn modulo-10: double every second digit from the right, add the digits of any result above nine, subtract the total from the next multiple of ten",
"alphabet": "0-9",
"lengths": [],
"minLength": 2,
"checkCharacters": 1,
"checkAlphabet": "0-9",
"checkPosition": "last character",
"scope": "Global. The generic algorithm behind payment card numbers, IMEIs, NPIs and the final step of an ISIN.",
"strictRules": null,
"detectsAllSingleCharacterErrors": true,
"undetectedSubstitutions": null,
"detectsAllAdjacentTranspositions": false,
"undetectedTranspositions": "Swapping an adjacent 0 and 9 is undetected, because both digits map to themselves when doubled. Every other adjacent transposition changes the check digit.",
"specification": "ISO/IEC 7812-1, Annex B",
"specificationUrl": "https://www.iso.org/standard/70484.html",
"meaning": "A correct Luhn digit means the digit string is internally consistent. On its own it says nothing about what the number identifies, who issued it or whether it was ever allocated."
},
{
"scheme": "gtin8",
"name": "GTIN-8 (EAN-8)",
"algorithm": "GS1 modulo-10: weights 3 and 1 alternating from the right, subtracted from the next multiple of ten",
"alphabet": "0-9",
"lengths": [
8
],
"minLength": 8,
"checkCharacters": 1,
"checkAlphabet": "0-9",
"checkPosition": "last character",
"scope": "Global GS1 key for very small packaging.",
"strictRules": null,
"detectsAllSingleCharacterErrors": true,
"undetectedSubstitutions": null,
"detectsAllAdjacentTranspositions": false,
"undetectedTranspositions": "Swapping two adjacent digits whose values differ by five is undetected (05↔50, 16↔61, 27↔72, 38↔83, 49↔94). Every other adjacent transposition changes the check digit.",
…
"generatedAt": "2026-07-29T08:13:22.000Z"
}
}
Only the Luhn-based schemes /api/check-digits?search=luhn
GET /api/check-digits?search=luhn
{
"data": [
{
"scheme": "luhn",
"name": "Luhn (generic mod-10)",
"algorithm": "Luhn modulo-10: double every second digit from the right, add the digits of any result above nine, subtract the total from the next multiple of ten",
"alphabet": "0-9",
"lengths": [],
"minLength": 2,
"checkCharacters": 1,
"checkAlphabet": "0-9",
"checkPosition": "last character",
"scope": "Global. The generic algorithm behind payment card numbers, IMEIs, NPIs and the final step of an ISIN.",
"strictRules": null,
"detectsAllSingleCharacterErrors": true,
"undetectedSubstitutions": null,
"detectsAllAdjacentTranspositions": false,
"undetectedTranspositions": "Swapping an adjacent 0 and 9 is undetected, because both digits map to themselves when doubled. Every other adjacent transposition changes the check digit.",
"specification": "ISO/IEC 7812-1, Annex B",
"specificationUrl": "https://www.iso.org/standard/70484.html",
"meaning": "A correct Luhn digit means the digit string is internally consistent. On its own it says nothing about what the number identifies, who issued it or whether it was ever allocated."
},
{
"scheme": "imei",
"name": "IMEI",
"algorithm": "Luhn modulo-10 over the fourteen TAC and serial digits",
"alphabet": "0-9",
"lengths": [
15
],
"minLength": 15,
"checkCharacters": 1,
"checkAlphabet": "0-9",
"checkPosition": "last character",
"scope": "Global, for GSM/UMTS/LTE/NR mobile equipment.",
"strictRules": null,
"detectsAllSingleCharacterErrors": true,
"undetectedSubstitutions": null,
"detectsAllAdjacentTranspositions": false,
"undetectedTranspositions": "Swapping an adjacent 0 and 9 is undetected, because both digits map to themselves when doubled. Every other adjacent transposition changes the check digit.",
…
"generatedAt": "2026-07-29T08:13:22.000Z"
}
}
The four GTIN lengths as CSV /api/check-digits?search=gtin&format=csv
GET /api/check-digits?search=gtin&format=csv
scheme,name,algorithm,alphabet,lengths,minLength,checkCharacters,checkAlphabet,checkPosition,scope,strictRules,detectsAllSingleCharacterErrors,undetectedSubstitutions,detectsAllAdjacentTranspositions,undetectedTranspositions,specification,specificationUrl,meaning
gtin8,GTIN-8 (EAN-8),"GS1 modulo-10: weights 3 and 1 alternating from the right, subtracted from the next multiple of ten",0-9,[8],8,1,0-9,last character,Global GS1 key for very small packaging.,,true,,false,"Swapping two adjacent digits whose values differ by five is undetected (05↔50, 16↔61, 27↔72, 38↔83, 49↔94). Every other adjacent transposition changes the check digit.",GS1 General Specifications — check-digit calculation,https://www.gs1.org/standards/barcodes/ean-upc,A correct check digit means the digits are internally consistent. It does not mean the GTIN has been allocated to a company or assigned to a product — this endpoint queries no GS1 registry and holds no product catalogue.
gtin12,GTIN-12 (UPC-A),"GS1 modulo-10: weights 3 and 1 alternating from the right, subtracted from the next multiple of ten",0-9,[12],12,1,0-9,last character,"Global GS1 key, printed as a UPC-A symbol and used mainly in North America.",,true,,false,"Swapping two adjacent digits whose values differ by five is undetected (05↔50, 16↔61, 27↔72, 38↔83, 49↔94). Every other adjacent transposition changes the check digit.",GS1 General Specifications — check-digit calculation,https://www.gs1.org/standards/barcodes/ean-upc,A correct check digit means the digits are internally consistent. It does not mean the GTIN has been allocated to a company or assigned to a product — this endpoint queries no GS1 registry and holds no product catalogue.
gtin13,GTIN-13 (EAN-13),"GS1 modulo-10: weights 3 and 1 alternating from the right, subtracted from the next multiple of ten",0-9,[13],13,1,0-9,last character,"Global GS1 key, printed as an EAN-13 symbol.",,true,,false,"Swapping two adjacent digits whose values differ by five is undetected (05↔50, 16↔61, 27↔72, 38↔83, 49↔94). Every other adjacent transposition changes the check digit.",GS1 General Specifications — check-digit calculation,https://www.gs1.org/standards/barcodes/ean-upc,A correct check digit means the digits are internally consistent. It does not mean the GTIN has been allocated to a company or assigned to a product — this endpoint queries no GS1 registry and holds no product catalogue.
gtin14,GTIN-14 (ITF-14 case code),"GS1 modulo-10: weights 3 and 1 alternating from the right, subtracted from the next multiple of ten",0-9,[14],14,1,0-9,last character,Global GS1 key for higher packaging levels; the first digit is the packaging indicator.,,true,,false,"Swapping two adjacent digits whose values differ by five is undetected (05↔50, 16↔61, 27↔72, 38↔83, 49↔94). Every other adjacent transposition changes the check digit.",GS1 General Specifications — check-digit calculation,https://www.gs1.org/standards/barcodes/ean-upc,A correct check digit means the digits are internally consistent. It does not mean the GTIN has been allocated to a company or assigned to a product — this endpoint queries no GS1 registry and holds no product catalogue.
GET/api/check-digits/validateCheck an identifier's check character and name the failing ruleComputed answer
Returns a structured verdict for any input: malformed values produce valid=false with ordered reason codes, never an error page.
Identifier scheme to apply. 'upca' is an alias for 'gtin12'. 'npi' and 'aba' are United States schemes, and the 'vin' check character is only enforced where the world manufacturer identifier's ISO 3780 region block is North American (1-5) or Chinese (L).
value
required
string
allowed: 1 – 64
example: 978-0-306-40615-7
The identifier to check, with or without spaces and hyphens. Whitespace is preserved when normalize=false so it shows up as an invalid character.
normalize
boolean
default: true
example: true
Remove ASCII spaces and hyphens before checking. ASCII letters are uppercased either way, because every scheme's alphabet is uppercase-only.
strict
boolean
default: false
example: true
Also enforce the scheme's structural rules (prefixes, VIN model-year code, Federal Reserve routing symbol). Schemes with no further rules answer with a warning.
schemeenumrequired
Identifier scheme to apply. 'upca' is an alias for 'gtin12'. 'npi' and 'aba' are United States schemes, and the 'vin' check character is only enforced where the world manufacturer identifier's ISO 3780 region block is North American (1-5) or Chinese (L).
The identifier to check, with or without spaces and hyphens. Whitespace is preserved when normalize=false so it shows up as an invalid character.
allowed: 1 – 64
example: value=978-0-306-40615-7
normalizeboolean
Remove ASCII spaces and hyphens before checking. ASCII letters are uppercased either way, because every scheme's alphabet is uppercase-only.
default: true
example: normalize=true
strictboolean
Also enforce the scheme's structural rules (prefixes, VIN model-year code, Federal Reserve routing symbol). Schemes with no further rules answer with a warning.
default: false
example: strict=true
Universal parametersShared response and formatting options4
Parameter
Type
Default & allowed
Description
fields
list
example: scheme,canonicalScheme
Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
exclude
list
example: notes
Return all fields except these (comma-separated).
pretty
boolean
default: false
example: true
Pretty-print the JSON response.
unwrap
boolean
default: false
example: true
Drop the envelope: return the raw array/object without data/meta wrapper.
fieldslist
Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
example: fields=scheme,canonicalScheme
excludelist
Return all fields except these (comma-separated).
example: exclude=notes
prettyboolean
Pretty-print the JSON response.
default: false
example: pretty=true
unwrapboolean
Drop the envelope: return the raw array/object without data/meta wrapper.
default: false
example: unwrap=true
Response schemaFields returned in each record18
Field
Type
Description
Example
scheme
string
Scheme id exactly as requested.
isbn13
canonicalScheme
string
Scheme actually applied — 'upca' resolves to 'gtin12'.
isbn13
input
string
The value exactly as supplied.
978-0-306-40615-7
normalized
string
Uppercased value, with ASCII spaces and hyphens removed when normalize is true.
9780306406157
valid
boolean
True only for this endpoint's checks: alphabet, length, check character (where applicable) and any strict rules. It never means the identifier was issued, assigned or registered.
true
reasons
string[]
Stable ordered failure codes — EMPTY_AFTER_NORMALIZATION, INVALID_CHARACTERS, WRONG_LENGTH, CHECK_CHARACTER_MISMATCH, STRICT_INVALID_PREFIX, STRICT_INVALID_MODEL_YEAR_CODE, STRICT_INVALID_ROUTING_SYMBOL. Empty exactly when valid is true.
[]
payloadnullable
string
The value without its check characters, or null when the value was too malformed to split.
978030640615
checkCharacternullable
string
The check character(s) found in the input, or null when the value could not be split.
7
expectedCheckCharacternullable
string
What the scheme's algorithm computes for that payload, or null when it could not be computed.
7
checkCharacterValid
boolean
Whether the supplied check character equals the computed one. Reported even when checkDigitApplicable is false, so a European VIN's position-9 result is still visible.
true
checkDigitApplicable
boolean
Whether this endpoint holds the check character against the value. Always true except for a complete VIN whose world manufacturer identifier falls outside the ISO 3780 North American (1-5) and Chinese (L) region blocks, where a mismatch never makes the VIN invalid. That is inferred from the WMI alone, so false means 'not determinable from the VIN alone', not 'not required' — 49 CFR 565 requires a check digit on any vehicle built for sale in the US whatever its WMI. Read checkCharacterValid for the strict answer.
true
actualLength
integer
Length of the normalized value.
13
expectedLengths
integer[]
Accepted total lengths, or an empty array for a variable-length scheme.
[13]
minLength
integer
Smallest accepted total length.
13
invalidCharacters
object[]
Every character outside the scheme's alphabet, in input order, as { index, character } with a zero-based index into the normalized value. When the length is wrong the check position cannot be located, so every character is tested against the scheme's full alphabet rather than the narrower check-position one. Empty when the alphabet check passed.
[{"index":4,"character":"#"}]
algorithm
string
The algorithm applied, in one sentence.
GS1 modulo-10 over the thirteen-digit Bookland EAN (weights 3 and 1 alternating from the right)
scope
string
Where this scheme and its check character actually apply.
Global.
notes
string[]
Situational explanations — VIN regional applicability, the upca alias, a 16-digit IMEISV, a failed strict rule, and the GS1 prefix caveat on every GTIN form. Empty when nothing needs saying.
[]
schemestring
Scheme id exactly as requested.
example: isbn13
canonicalSchemestring
Scheme actually applied — 'upca' resolves to 'gtin12'.
example: isbn13
inputstring
The value exactly as supplied.
example: 978-0-306-40615-7
normalizedstring
Uppercased value, with ASCII spaces and hyphens removed when normalize is true.
example: 9780306406157
validboolean
True only for this endpoint's checks: alphabet, length, check character (where applicable) and any strict rules. It never means the identifier was issued, assigned or registered.
example: true
reasonsstring[]
Stable ordered failure codes — EMPTY_AFTER_NORMALIZATION, INVALID_CHARACTERS, WRONG_LENGTH, CHECK_CHARACTER_MISMATCH, STRICT_INVALID_PREFIX, STRICT_INVALID_MODEL_YEAR_CODE, STRICT_INVALID_ROUTING_SYMBOL. Empty exactly when valid is true.
example: []
payloadstringnullable
The value without its check characters, or null when the value was too malformed to split.
example: 978030640615
checkCharacterstringnullable
The check character(s) found in the input, or null when the value could not be split.
example: 7
expectedCheckCharacterstringnullable
What the scheme's algorithm computes for that payload, or null when it could not be computed.
example: 7
checkCharacterValidboolean
Whether the supplied check character equals the computed one. Reported even when checkDigitApplicable is false, so a European VIN's position-9 result is still visible.
example: true
checkDigitApplicableboolean
Whether this endpoint holds the check character against the value. Always true except for a complete VIN whose world manufacturer identifier falls outside the ISO 3780 North American (1-5) and Chinese (L) region blocks, where a mismatch never makes the VIN invalid. That is inferred from the WMI alone, so false means 'not determinable from the VIN alone', not 'not required' — 49 CFR 565 requires a check digit on any vehicle built for sale in the US whatever its WMI. Read checkCharacterValid for the strict answer.
example: true
actualLengthinteger
Length of the normalized value.
example: 13
expectedLengthsinteger[]
Accepted total lengths, or an empty array for a variable-length scheme.
example: [13]
minLengthinteger
Smallest accepted total length.
example: 13
invalidCharactersobject[]
Every character outside the scheme's alphabet, in input order, as { index, character } with a zero-based index into the normalized value. When the length is wrong the check position cannot be located, so every character is tested against the scheme's full alphabet rather than the narrower check-position one. Empty when the alphabet check passed.
example: [{"index":4,"character":"#"}]
algorithmstring
The algorithm applied, in one sentence.
example: GS1 modulo-10 over the thirteen-digit Bookland EAN (weights 3 and 1 alternating from the right)
scopestring
Where this scheme and its check character actually apply.
example: Global.
notesstring[]
Situational explanations — VIN regional applicability, the upca alias, a 16-digit IMEISV, a failed strict rule, and the GS1 prefix caveat on every GTIN form. Empty when nothing needs saying.
example: []
Documented examples
Build-generated requests and complete responses6
Check a published ISBN-13 /api/check-digits/validate?scheme=isbn13&value=978-0-306-40615-7
GET /api/check-digits/validate?scheme=isbn13&value=978-0-306-40615-7
A European VIN has no position-9 check digit /api/check-digits/validate?scheme=vin&value=WVWZZZ1JZXW000010
GET /api/check-digits/validate?scheme=vin&value=WVWZZZ1JZXW000010
{
"data": {
"scheme": "vin",
"canonicalScheme": "vin",
"input": "WVWZZZ1JZXW000010",
"normalized": "WVWZZZ1JZXW000010",
"valid": true,
"reasons": [],
"payload": "WVWZZZ1JXW000010",
"checkCharacter": "Z",
"expectedCheckCharacter": "1",
"checkCharacterValid": false,
"checkDigitApplicable": false,
"actualLength": 17,
"expectedLengths": [
17
],
"minLength": 17,
"invalidCharacters": [],
"algorithm": "ISO 3779 transliteration, weights 8-7-6-5-4-3-2-10-0-9-8-7-6-5-4-3-2, modulo 11; remainder 10 is written as X",
"scope": "The VIN is global; the position-9 check character is not. 49 CFR 565 requires one on every vehicle manufactured for sale in the United States and GB 16735 requires one in China, while no United Kingdom or European Union rule does. A VIN does not record which market it was built for, so this endpoint infers applicability from the ISO 3780 region block of the world manufacturer identifier alone and never marks a VIN outside the 1-5 and L blocks invalid on the check character.",
"notes": [
"The world manufacturer identifier 'WVW' begins with 'W', outside the ISO 3780 North American (1-5) and Chinese (L) region blocks, so position 9 is reported but never makes this VIN invalid. That is inferred from the WMI alone and is not the regulation: 49 CFR 565 requires a check digit on every vehicle manufactured for sale in the United States whatever its WMI, so a US-market European, Japanese or Korean vehicle does carry one. Read checkCharacterValid when you need the strict answer."
]
},
"meta": {
"endpoint": "check-digits",
"route": "/validate",
"params": {
"scheme": "vin",
"value": "WVWZZZ1JZXW000010",
"normalize": true,
"strict": false
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
}
Explain a mistyped EAN-13 /api/check-digits/validate?scheme=gtin13&value=5901234123458
GET /api/check-digits/validate?scheme=gtin13&value=5901234123458
{
"data": {
"scheme": "gtin13",
"canonicalScheme": "gtin13",
"input": "5901234123458",
"normalized": "5901234123458",
"valid": false,
"reasons": [
"CHECK_CHARACTER_MISMATCH"
],
"payload": "590123412345",
"checkCharacter": "8",
"expectedCheckCharacter": "7",
"checkCharacterValid": false,
"checkDigitApplicable": true,
"actualLength": 13,
"expectedLengths": [
13
],
"minLength": 13,
"invalidCharacters": [],
"algorithm": "GS1 modulo-10: weights 3 and 1 alternating from the right, subtracted from the next multiple of ten",
"scope": "Global GS1 key, printed as an EAN-13 symbol.",
"notes": [
"The leading digits identify the GS1 Member Organisation that issued the company prefix. They are not a country of origin, a country of manufacture or a company address."
]
},
"meta": {
"endpoint": "check-digits",
"route": "/validate",
"params": {
"scheme": "gtin13",
"value": "5901234123458",
"normalize": true,
"strict": false
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
}
Strict mode rejects a non-ISBN prefix /api/check-digits/validate?scheme=isbn13&value=5901234123457&strict=true
GET /api/check-digits/validate?scheme=isbn13&value=5901234123457&strict=true
{
"data": {
"scheme": "isbn13",
"canonicalScheme": "isbn13",
"input": "5901234123457",
"normalized": "5901234123457",
"valid": false,
"reasons": [
"STRICT_INVALID_PREFIX"
],
"payload": "590123412345",
"checkCharacter": "7",
"expectedCheckCharacter": "7",
"checkCharacterValid": true,
"checkDigitApplicable": true,
"actualLength": 13,
"expectedLengths": [
13
],
"minLength": 13,
"invalidCharacters": [],
"algorithm": "GS1 modulo-10 over the thirteen-digit Bookland EAN (weights 3 and 1 alternating from the right)",
"scope": "Global.",
"notes": [
"ISBN-13 values carry the Bookland prefix 978 or 979 (excluding 979-0). '590' is a valid GTIN-13 but not an ISBN."
]
},
"meta": {
"endpoint": "check-digits",
"route": "/validate",
"params": {
"scheme": "isbn13",
"value": "5901234123457",
"normalize": true,
"strict": true
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
}
Check an ISIN /api/check-digits/validate?scheme=isin&value=US0378331005
GET /api/check-digits/validate?scheme=isin&value=US0378331005
GET/api/check-digits/computeReturn the check character a payload is missingComputed answer
Takes the identifier without its check character(s) and returns both the character and the completed value. A malformed payload answers computable=false with reason codes.
Identifier scheme to apply. 'upca' is an alias for 'gtin12'. 'npi' and 'aba' are United States schemes, and the 'vin' check character is only enforced where the world manufacturer identifier's ISO 3780 region block is North American (1-5) or Chinese (L).
value
required
string
allowed: 1 – 64
example: 590123412345
The payload without its check character(s) — twelve digits for a GTIN-13, nine for an ISBN-10 or NPI, eighteen for a LEI. For a VIN, pass either the sixteen characters around position 9 or a full seventeen-character VIN whose position 9 is a placeholder.
normalize
boolean
default: true
example: true
Remove ASCII spaces and hyphens before checking. ASCII letters are uppercased either way, because every scheme's alphabet is uppercase-only.
schemeenumrequired
Identifier scheme to apply. 'upca' is an alias for 'gtin12'. 'npi' and 'aba' are United States schemes, and the 'vin' check character is only enforced where the world manufacturer identifier's ISO 3780 region block is North American (1-5) or Chinese (L).
The payload without its check character(s) — twelve digits for a GTIN-13, nine for an ISBN-10 or NPI, eighteen for a LEI. For a VIN, pass either the sixteen characters around position 9 or a full seventeen-character VIN whose position 9 is a placeholder.
allowed: 1 – 64
example: value=590123412345
normalizeboolean
Remove ASCII spaces and hyphens before checking. ASCII letters are uppercased either way, because every scheme's alphabet is uppercase-only.
default: true
example: normalize=true
Universal parametersShared response and formatting options4
Parameter
Type
Default & allowed
Description
fields
list
example: scheme,canonicalScheme
Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
exclude
list
example: notes
Return all fields except these (comma-separated).
pretty
boolean
default: false
example: true
Pretty-print the JSON response.
unwrap
boolean
default: false
example: true
Drop the envelope: return the raw array/object without data/meta wrapper.
fieldslist
Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
example: fields=scheme,canonicalScheme
excludelist
Return all fields except these (comma-separated).
example: exclude=notes
prettyboolean
Pretty-print the JSON response.
default: false
example: pretty=true
unwrapboolean
Drop the envelope: return the raw array/object without data/meta wrapper.
default: false
example: unwrap=true
Response schemaFields returned in each record15
Field
Type
Description
Example
scheme
string
Scheme id exactly as requested.
gtin13
canonicalScheme
string
Scheme actually applied — 'upca' resolves to 'gtin12'.
gtin13
input
string
The payload exactly as supplied.
590123412345
payloadnullable
string
Normalized payload used for the computation, or null when it was not computable.
590123412345
checkCharacternullable
string
The computed check character(s), or null when not computable.
7
valuenullable
string
The complete identifier, with the check character inserted where the scheme puts it (position 9 for a VIN, otherwise appended). Null when not computable.
5901234123457
computable
boolean
Whether a check character could be computed at all.
true
reasons
string[]
Stable ordered failure codes — EMPTY_AFTER_NORMALIZATION, INVALID_CHARACTERS, WRONG_PAYLOAD_LENGTH. Empty exactly when computable is true.
[]
invalidCharacters
object[]
Every character outside the scheme's alphabet, in input order, as { index, character } with a zero-based index into the normalized value. When the length is wrong the check position cannot be located, so every character is tested against the scheme's full alphabet rather than the narrower check-position one. Empty when the alphabet check passed.
[{"index":4,"character":"#"}]
expectedPayloadLengths
integer[]
Accepted payload lengths (total length minus the check characters). Empty for variable-length schemes; VIN accepts 16 or a full 17.
[12]
actualPayloadLength
integer
Length of the normalized payload as supplied.
12
checkDigitApplicable
boolean
Whether this endpoint would hold the computed character against the completed value. Always true except for a VIN whose world manufacturer identifier falls outside the ISO 3780 North American (1-5) and Chinese (L) region blocks — an inference from the WMI, not the regulation, so the value is still returned with the character in place and an explanatory note.
true
algorithm
string
The algorithm applied, in one sentence.
GS1 modulo-10: weights 3 and 1 alternating from the right, subtracted from the next multiple of ten
scope
string
Where this scheme and its check character actually apply.
Global GS1 key, printed as an EAN-13 symbol.
notes
string[]
Situational explanations, such as a VIN placeholder form or the GS1 prefix caveat.
[]
schemestring
Scheme id exactly as requested.
example: gtin13
canonicalSchemestring
Scheme actually applied — 'upca' resolves to 'gtin12'.
example: gtin13
inputstring
The payload exactly as supplied.
example: 590123412345
payloadstringnullable
Normalized payload used for the computation, or null when it was not computable.
example: 590123412345
checkCharacterstringnullable
The computed check character(s), or null when not computable.
example: 7
valuestringnullable
The complete identifier, with the check character inserted where the scheme puts it (position 9 for a VIN, otherwise appended). Null when not computable.
example: 5901234123457
computableboolean
Whether a check character could be computed at all.
example: true
reasonsstring[]
Stable ordered failure codes — EMPTY_AFTER_NORMALIZATION, INVALID_CHARACTERS, WRONG_PAYLOAD_LENGTH. Empty exactly when computable is true.
example: []
invalidCharactersobject[]
Every character outside the scheme's alphabet, in input order, as { index, character } with a zero-based index into the normalized value. When the length is wrong the check position cannot be located, so every character is tested against the scheme's full alphabet rather than the narrower check-position one. Empty when the alphabet check passed.
example: [{"index":4,"character":"#"}]
expectedPayloadLengthsinteger[]
Accepted payload lengths (total length minus the check characters). Empty for variable-length schemes; VIN accepts 16 or a full 17.
example: [12]
actualPayloadLengthinteger
Length of the normalized payload as supplied.
example: 12
checkDigitApplicableboolean
Whether this endpoint would hold the computed character against the completed value. Always true except for a VIN whose world manufacturer identifier falls outside the ISO 3780 North American (1-5) and Chinese (L) region blocks — an inference from the WMI, not the regulation, so the value is still returned with the character in place and an explanatory note.
example: true
algorithmstring
The algorithm applied, in one sentence.
example: GS1 modulo-10: weights 3 and 1 alternating from the right, subtracted from the next multiple of ten
scopestring
Where this scheme and its check character actually apply.
example: Global GS1 key, printed as an EAN-13 symbol.
notesstring[]
Situational explanations, such as a VIN placeholder form or the GS1 prefix caveat.
example: []
Documented examples
Build-generated requests and complete responses5
EAN-13 check digit for twelve digits /api/check-digits/compute?scheme=gtin13&value=590123412345
GET /api/check-digits/compute?scheme=gtin13&value=590123412345
{
"data": {
"scheme": "gtin13",
"canonicalScheme": "gtin13",
"input": "590123412345",
"payload": "590123412345",
"checkCharacter": "7",
"value": "5901234123457",
"computable": true,
"reasons": [],
"invalidCharacters": [],
"expectedPayloadLengths": [
12
],
"actualPayloadLength": 12,
"checkDigitApplicable": true,
"algorithm": "GS1 modulo-10: weights 3 and 1 alternating from the right, subtracted from the next multiple of ten",
"scope": "Global GS1 key, printed as an EAN-13 symbol.",
"notes": [
"The leading digits identify the GS1 Member Organisation that issued the company prefix. They are not a country of origin, a country of manufacture or a company address."
]
},
"meta": {
"endpoint": "check-digits",
"route": "/compute",
"params": {
"scheme": "gtin13",
"value": "590123412345",
"normalize": true
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
}
An ISBN-10 whose check character is X /api/check-digits/compute?scheme=isbn10&value=043942089
GET /api/check-digits/compute?scheme=isbn10&value=043942089
{
"data": {
"scheme": "isbn10",
"canonicalScheme": "isbn10",
"input": "043942089",
"payload": "043942089",
"checkCharacter": "X",
"value": "043942089X",
"computable": true,
"reasons": [],
"invalidCharacters": [],
"expectedPayloadLengths": [
9
],
"actualPayloadLength": 9,
"checkDigitApplicable": true,
"algorithm": "Modulo-11 with descending weights 10…2; remainder 10 is written as X",
"scope": "Global. Withdrawn for new assignments in 2007 but still present in legacy catalogues; every ISBN-10 has an equivalent 978-prefixed ISBN-13.",
"notes": []
},
"meta": {
"endpoint": "check-digits",
"route": "/compute",
"params": {
"scheme": "isbn10",
"value": "043942089",
"normalize": true
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
}
VIN check character from a 16-character payload /api/check-digits/compute?scheme=vin&value=1HGCM8263A004352
GET /api/check-digits/compute?scheme=vin&value=1HGCM8263A004352
{
"data": {
"scheme": "vin",
"canonicalScheme": "vin",
"input": "1HGCM8263A004352",
"payload": "1HGCM8263A004352",
"checkCharacter": "3",
"value": "1HGCM82633A004352",
"computable": true,
"reasons": [],
"invalidCharacters": [],
"expectedPayloadLengths": [
16,
17
],
"actualPayloadLength": 16,
"checkDigitApplicable": true,
"algorithm": "ISO 3779 transliteration, weights 8-7-6-5-4-3-2-10-0-9-8-7-6-5-4-3-2, modulo 11; remainder 10 is written as X",
"scope": "The VIN is global; the position-9 check character is not. 49 CFR 565 requires one on every vehicle manufactured for sale in the United States and GB 16735 requires one in China, while no United Kingdom or European Union rule does. A VIN does not record which market it was built for, so this endpoint infers applicability from the ISO 3780 region block of the world manufacturer identifier alone and never marks a VIN outside the 1-5 and L blocks invalid on the check character.",
"notes": [
"The world manufacturer identifier '1HG' begins with '1', the ISO 3780 North American region block, so this VIN is treated as one 49 CFR 565 covers and the position-9 check character is required."
]
},
"meta": {
"endpoint": "check-digits",
"route": "/compute",
"params": {
"scheme": "vin",
"value": "1HGCM8263A004352",
"normalize": true
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
}
LEI check-digit pair /api/check-digits/compute?scheme=lei&value=L3I9ZG2KFGXZ61BMYR
GET /api/check-digits/compute?scheme=lei&value=L3I9ZG2KFGXZ61BMYR
{
"data": {
"scheme": "lei",
"canonicalScheme": "lei",
"input": "L3I9ZG2KFGXZ61BMYR",
"payload": "L3I9ZG2KFGXZ61BMYR",
"checkCharacter": "72",
"value": "L3I9ZG2KFGXZ61BMYR72",
"computable": true,
"reasons": [],
"invalidCharacters": [],
"expectedPayloadLengths": [
18
],
"actualPayloadLength": 18,
"checkDigitApplicable": true,
"algorithm": "ISO/IEC 7064 MOD 97-10 over the twenty characters with letters expanded A=10…Z=35; a valid LEI leaves remainder 1",
"scope": "Global, for legal entities in financial transactions.",
"notes": [
"ISO 17442 reserves characters 5 and 6 as '00', but some registered LEIs do not follow that convention, so this endpoint does not treat it as a validity rule."
]
},
"meta": {
"endpoint": "check-digits",
"route": "/compute",
"params": {
"scheme": "lei",
"value": "L3I9ZG2KFGXZ61BMYR",
"normalize": true
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
}
GET /api/check-digits/compute?scheme=npi&value=123456789
{
"data": {
"scheme": "npi",
"canonicalScheme": "npi",
"input": "123456789",
"payload": "123456789",
"checkCharacter": "3",
"value": "1234567893",
"computable": true,
"reasons": [],
"invalidCharacters": [],
"expectedPayloadLengths": [
9
],
"actualPayloadLength": 9,
"checkDigitApplicable": true,
"algorithm": "Luhn modulo-10 over 80840 followed by the nine-digit payload",
"scope": "United States only. The National Provider Identifier is issued by CMS for US health care providers; it has no meaning elsewhere.",
"notes": []
},
"meta": {
"endpoint": "check-digits",
"route": "/compute",
"params": {
"scheme": "npi",
"value": "123456789",
"normalize": true
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
}
GET/api/check-digits/convertConvert between equivalent GTIN and ISBN formsComputed answer
Detects the source form from its length, verifies its own check character, then re-expresses it as the target and recomputes the check character.
Source identifier: a GTIN-8, ISBN-10, GTIN-12/UPC-A, GTIN-13/ISBN-13 or GTIN-14. Spaces and hyphens are always removed. Its own check character must be correct.
to
required
enum
allowed: gtin13 | gtin14 | upca | isbn10 | isbn13
example: gtin13
Target form. Conversions that do not exist — a GTIN-14 above indicator 0, a GTIN-13 without a leading zero to UPC-A, a 979-prefixed ISBN-13 to ISBN-10 — return a 400 explaining why.
valuestringrequired
Source identifier: a GTIN-8, ISBN-10, GTIN-12/UPC-A, GTIN-13/ISBN-13 or GTIN-14. Spaces and hyphens are always removed. Its own check character must be correct.
allowed: 1 – 64
example: value=036000291452
toenumrequired
Target form. Conversions that do not exist — a GTIN-14 above indicator 0, a GTIN-13 without a leading zero to UPC-A, a 979-prefixed ISBN-13 to ISBN-10 — return a 400 explaining why.
allowed: gtin13 | gtin14 | upca | isbn10 | isbn13
example: to=gtin13
Universal parametersShared response and formatting options4
Parameter
Type
Default & allowed
Description
fields
list
example: input,normalized
Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
exclude
list
example: notes
Return all fields except these (comma-separated).
pretty
boolean
default: false
example: true
Pretty-print the JSON response.
unwrap
boolean
default: false
example: true
Drop the envelope: return the raw array/object without data/meta wrapper.
fieldslist
Return only these fields (comma-separated). Mutually exclusive with 'exclude'.
example: fields=input,normalized
excludelist
Return all fields except these (comma-separated).
example: exclude=notes
prettyboolean
Pretty-print the JSON response.
default: false
example: pretty=true
unwrapboolean
Drop the envelope: return the raw array/object without data/meta wrapper.
default: false
example: unwrap=true
Response schemaFields returned in each record9
Field
Type
Description
Example
input
string
The source value exactly as supplied.
036000291452
normalized
string
Uppercased source with ASCII spaces and hyphens removed.
036000291452
sourceForm
string
Detected source form: gtin8, isbn10, gtin12, gtin13 or gtin14.
gtin12
sourceCheckCharacter
string
The source's own (verified) check character.
2
to
string
Requested target form.
gtin13
value
string
The converted identifier, with its check character recomputed for the target form.
0036000291452
checkCharacter
string
Check character of the converted value.
2
checkCharacterChanged
boolean
Whether the converted value's check character literally differs from the source's. Zero-padding between GTIN forms never changes it, because GS1 weights run from the right. An ISBN-10 ↔ ISBN-13 conversion always recomputes it under the other algorithm, but about one such conversion in ten lands on the same character and so reports false.
false
notes
string[]
What the conversion did and any caveat that applies to it.
[]
inputstring
The source value exactly as supplied.
example: 036000291452
normalizedstring
Uppercased source with ASCII spaces and hyphens removed.
example: 036000291452
sourceFormstring
Detected source form: gtin8, isbn10, gtin12, gtin13 or gtin14.
example: gtin12
sourceCheckCharacterstring
The source's own (verified) check character.
example: 2
tostring
Requested target form.
example: gtin13
valuestring
The converted identifier, with its check character recomputed for the target form.
example: 0036000291452
checkCharacterstring
Check character of the converted value.
example: 2
checkCharacterChangedboolean
Whether the converted value's check character literally differs from the source's. Zero-padding between GTIN forms never changes it, because GS1 weights run from the right. An ISBN-10 ↔ ISBN-13 conversion always recomputes it under the other algorithm, but about one such conversion in ten lands on the same character and so reports false.
example: false
notesstring[]
What the conversion did and any caveat that applies to it.
example: []
Documented examples
Build-generated requests and complete responses4
UPC-A to GTIN-13 /api/check-digits/convert?value=036000291452&to=gtin13
GET /api/check-digits/convert?value=036000291452&to=gtin13
{
"data": {
"input": "036000291452",
"normalized": "036000291452",
"sourceForm": "gtin12",
"sourceCheckCharacter": "2",
"to": "gtin13",
"value": "0036000291452",
"checkCharacter": "2",
"checkCharacterChanged": false,
"notes": [
"GS1 represents a shorter GTIN in a longer data field by right-justifying it with leading zeros. The check digit is unchanged because GS1 weights are assigned from the right."
]
},
"meta": {
"endpoint": "check-digits",
"route": "/convert",
"params": {
"value": "036000291452",
"to": "gtin13"
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
}
ISBN-13 back to ISBN-10 /api/check-digits/convert?value=9780306406157&to=isbn10
GET /api/check-digits/convert?value=9780306406157&to=isbn10
{
"data": {
"input": "9780306406157",
"normalized": "9780306406157",
"sourceForm": "gtin13",
"sourceCheckCharacter": "7",
"to": "isbn10",
"value": "0306406152",
"checkCharacter": "2",
"checkCharacterChanged": true,
"notes": [
"This GTIN-13 carries a Bookland prefix, so it is also an ISBN-13.",
"The 978 prefix is dropped and the modulo-11 check character (0-9 or X) is recomputed from the remaining nine digits."
]
},
"meta": {
"endpoint": "check-digits",
"route": "/convert",
"params": {
"value": "9780306406157",
"to": "isbn10"
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
}
ISBN-10 forward to ISBN-13 /api/check-digits/convert?value=0-306-40615-2&to=isbn13
GET /api/check-digits/convert?value=0-306-40615-2&to=isbn13
{
"data": {
"input": "0-306-40615-2",
"normalized": "0306406152",
"sourceForm": "isbn10",
"sourceCheckCharacter": "2",
"to": "isbn13",
"value": "9780306406157",
"checkCharacter": "7",
"checkCharacterChanged": true,
"notes": [
"ISBN-10 uses a modulo-11 check character (0-9 or X) while ISBN-13 and the GTIN forms use the GS1 modulo-10 check digit, so the check character is recomputed rather than carried over."
]
},
"meta": {
"endpoint": "check-digits",
"route": "/convert",
"params": {
"value": "0-306-40615-2",
"to": "isbn13"
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
}
GTIN-13 to a case-level GTIN-14 /api/check-digits/convert?value=5901234123457&to=gtin14
GET /api/check-digits/convert?value=5901234123457&to=gtin14
{
"data": {
"input": "5901234123457",
"normalized": "5901234123457",
"sourceForm": "gtin13",
"sourceCheckCharacter": "7",
"to": "gtin14",
"value": "05901234123457",
"checkCharacter": "7",
"checkCharacterChanged": false,
"notes": [
"GS1 represents a shorter GTIN in a longer data field by right-justifying it with leading zeros. The check digit is unchanged because GS1 weights are assigned from the right.",
"Packaging indicator 0 identifies the base trade item. A GTIN-14 built with indicator 0 keeps the source check digit; indicators 1-9 describe higher packaging levels and are assigned by the brand owner, not derived."
]
},
"meta": {
"endpoint": "check-digits",
"route": "/convert",
"params": {
"value": "5901234123457",
"to": "gtin14"
},
"generatedAt": "2026-07-29T08:13:22.000Z"
}
}
About this API
Coverage, behavior and common use cases
Coverage & behavior
Nineteen check-character schemes, each implemented straight from its published algorithm and each reporting which rule failed, not just a boolean. /validate checks an identifier, /compute returns the character a payload is missing, /convert moves between equivalent GTIN and ISBN forms, and the root route documents every scheme's algorithm, alphabet, length rules and error-detection limits.
A valid check digit means well-formed — nothing more. It does not mean the identifier was issued, assigned, registered, listed, enumerated or is tradeable. This endpoint holds no product catalogue, securities master, vehicle history, device database or provider registry, and it makes no network calls, so it cannot tell you whether a number belongs to anything real.
Regional scope matters, and we say exactly how far we can see. The VIN check character at position 9 is required by 49 CFR 565 on vehicles manufactured for sale in the United States and by GB 16735 in China; no United Kingdom or European Union rule requires one. A VIN does not record which market it was built for, so scheme=vin reads the ISO 3780 region block of the world manufacturer identifier and returns checkDigitApplicable: false outside the 1-5 and L blocks, where a position-9 mismatch is reported in checkCharacterValid but never makes valid false. That is an inference, not the regulation: a US-market BMW, Toyota or Hyundai carries a mandatory check digit under a W, J or K WMI, so checkDigitApplicable: false means "not determinable from the VIN alone" — read checkCharacterValid when you need the strict answer. npi and aba are United States schemes and say so in their own scope field.
Error detection is not universal, so each scheme states its own limits. Mod-10 systems cannot see every transposition: Luhn (and therefore IMEI, NPI and the last step of ISIN) misses the 09 ↔ 90 swap, while the GS1 and ABA weightings miss adjacent digits five apart. The modulus-11 and modulus-97 systems — ISBN-10, ISSN, ISO 7064 MOD 11-2 and MOD 97-10 — catch every adjacent transposition; ISO 7064 MOD 11,10 misses a small minority, and ISIN misses every adjacent letter-letter swap, the country prefix included. ISIN, LEI and VIN do not even catch every single-character substitution: VIN's transliteration table is many-to-one, so A and J are indistinguishable to the check character, while ISIN and LEI expand letters into two digits, so a letter-for-digit substitution changes the arithmetic's shape rather than just one term. Every scheme record carries detectsAllSingleCharacterErrors and detectsAllAdjacentTranspositions, plus a plain-English description of exactly what slips through when something does.
Errors are structured, not thrown. A wrong length or an out-of-alphabet character produces a valid: false record with ordered reasons codes and an invalidCharacters list naming each offending character and its index. Beyond the platform's ordinary parameter validation — a missing value, a value over 64 characters, an unrecognized scheme or to — the only 400 this endpoint raises is a /convert request that is genuinely impossible.
strict=false (the default) checks alphabet, length and check character only. strict=true adds the specification's structural rules where they exist: the ISBN-13 Bookland prefix (978, or 979 other than 979-0, which is the ISMN prefix), the ISMN 9790 prefix, the two-letter ISIN prefix, the North-American VIN model-year code and the allocated Federal Reserve routing symbols. For the fourteen schemes with no further rules, strict=true returns a warning saying so rather than pretending to do more.
Deliberate exclusions. National identity numbers are out of scope entirely. GS1 prefix → company or country lookup is out of scope: the table is not ours to redistribute, and "prefix equals country of origin" is false in any case — the leading digits identify the GS1 Member Organisation that issued the company prefix. ISBN hyphenation is out of scope because the ISBN range message is not redistributable. IBAN national layouts stay in the ibans endpoint; this one owns the generic ISO 7064 MOD 97-10 algorithm. GS1 and ISO standards texts are paywalled: we implement and cite the published algorithms, we do not reproduce the standards.
Use it for
→ Validate an EAN-13 or UPC-A payload before sending it to a label printer
→ Compute the missing ISBN-10 or ISBN-13 check character during a catalogue import
→ Reject mistyped IMEIs in a device-enrolment form without shipping a Luhn implementation
→ Convert a 12-digit UPC-A into the GTIN-13 and GTIN-14 forms a warehouse system expects
→ Tell a support agent exactly which rule a rejected VIN, ISIN or LEI broke
Frequently asked questions
Practical answers about this endpoint6
How do I validate an IMEI number?
Call /api/check-digits/validate?scheme=imei&value=490154203237518. It runs the Luhn check that 3GPP TS 23.003 defines over the fourteen TAC and serial digits. A pass means the fifteen digits are well formed — it does not mean the device exists or that the Type Allocation Code was ever issued.
How is the EAN-13 or UPC check digit calculated?
GS1 weights the data digits 3 and 1 alternately from the right, sums them and subtracts the total from the next multiple of ten. /api/check-digits/compute?scheme=gtin13&value=590123412345 returns the digit, and the identical rule covers GTIN-8, GTIN-12/UPC-A and GTIN-14.
Does a GS1 or EAN prefix tell you the country of origin?
No. The leading digits identify the GS1 Member Organisation that issued the company prefix — not where a product was made, nor where the company is based. A firm can join GS1 in one country and manufacture anywhere, so this endpoint deliberately ships no prefix-to-country table.
Why does a European VIN fail other check digit calculators?
Because position 9 is a check character only where a regulator requires it — 49 CFR 565 in the United States, GB 16735 in China — and no UK or EU rule does. A VIN does not record its market, so this endpoint reads the ISO 3780 region block of the world manufacturer identifier: outside the 1-5 and L blocks it returns checkDigitApplicable: false and never lets a position-9 mismatch make valid false. That is an inference, not the regulation, so read checkCharacterValid for the strict answer — a US-market BMW or Toyota does carry a mandatory check digit.
Can I convert an ISBN-13 back to an ISBN-10?
Only when the prefix is 978. /api/check-digits/convert?value=9780306406157&to=isbn10 drops the prefix and recomputes the modulo-11 character. A 979-prefixed ISBN-13 has no ISBN-10 at all and returns a 400 that says exactly that.
Which typing errors does a check digit actually catch?
Every scheme here catches all single-character substitutions except ISIN, LEI and VIN, where expanding or transliterating letters into digits either collapses characters onto the same contribution (VIN) or changes the length of the string being weighed (ISIN, LEI — so 0 typed as O can slip through). Adjacent transpositions vary: Luhn misses only 09 ↔ 90, the GS1 and ABA mod-10 weightings miss digits five apart, ISO 7064 MOD 11,10 misses a small minority, ISIN misses every letter-letter swap, and the modulus-11 and modulus-97 systems miss none. Each scheme record spells out its own limits.