Academic Publishing Validation
Four academic identifiers, one submission workflow. Here's how to validate a DOI, ORCID researcher ID, ISBN, and ISSN when building academic publishing platforms, citation managers, or repository submission systems.
In this guide
1. The academic identifier validation problem
Academic publishing platforms need to validate multiple identifier types at once. A journal submission system must confirm the author's ORCID is valid, the DOI format is correct (and optionally resolve metadata), referenced ISBNs are structurally sound, and the journal's ISSN is registered.
Invalid identifiers cause broken links, failed CrossRef DOI registrations, metadata errors in indexing databases like PubMed and Scopus, and rejected submissions. A single malformed ORCID can block an author from being credited in a deposit.
The solution: validate all relevant identifiers in parallel at submission time, enriching the metadata and catching errors before they propagate into the scholarly record.
2. The four identifiers
| Validator | What it validates | When to use | API endpoint |
|---|---|---|---|
| DOI | Format (10.prefix/suffix) + optional CrossRef metadata | Article/dataset DOI validation | GET /v0/doi |
| ORCID | 16-digit format (MOD-11-2) + optional profile lookup | Author identity verification | GET /v0/orcid |
| ISBN | ISBN-10/ISBN-13 check digit + normalization | Book references, citation validation | GET /v0/isbn |
| ISSN | MOD-11 check digit for serial publications | Journal ISSN validation | GET /v0/issn |
3. Step 1: Validate the DOI
A Digital Object Identifier (DOI) follows the format 10.prefix/suffix. The endpoint validates:
- Format validation — confirms the 10. prefix and non-empty suffix
- Registrant identification — the numeric prefix identifies the CrossRef registrant
- Metadata lookup — optionally resolves title, authors, publisher, and publication date via CrossRef
Example response
{ "valid": true, "doi": "10.1038/nature12373", "prefix": "10.1038", "suffix": "nature12373", "registrantCode": "1038", "registrant": "Nature Publishing Group", "url": "https://doi.org/10.1038/nature12373", "metadata": { "found": true, "title": "Gravitational waves from binary pulsars", "authors": ["J. H. Taylor"], "publisher": "Springer Science and Business Media LLC", "type": "journal-article", "issued": [[1994, 1]] } }
What to check in your code
valid === true — the DOI follows the 10.prefix/suffix format
metadata.found — CrossRef has a record; use title/authors to pre-fill the citation form
url — the canonical DOI resolver URL to store for linking
4. Step 2: Validate the ORCID
An ORCID (Open Researcher and Contributor ID) is a 16-digit identifier in four groups of four digits (XXXX-XXXX-XXXX-XXXX), with the last character being a MOD-11-2 check digit (0–9 or X). The endpoint validates:
- Format and checksum — 16-digit ORCID with MOD-11-2 check
- Public profile lookup — optionally retrieves the researcher's name and institution
Example response
{ "valid": true, "formatted": "0000-0002-1825-0097", "uri": "https://orcid.org/0000-0002-1825-0097", "profile": { "found": true, "givenNames": "Josiah", "familyName": "Carberry", "organization": "Brown University" } }
What to check in your code
valid === true — the ORCID passes format and MOD-11-2 checksum validation
uri — store the canonical ORCID URI for linking and interoperability
profile.found — profile not found may mean private ORCID; do not reject the author
5. Step 3: Validate the ISBN
ISBN (International Standard Book Number) exists in two formats: ISBN-10 (legacy) and ISBN-13 (current standard). The endpoint accepts both and normalizes to ISBN-13:
Example response
{ "valid": true, "format": "ISBN-13", "isbn10": "3161484100", "isbn13": "9783161484100" }
What to check in your code
valid === true — the check digit is valid for the detected format
isbn13 — always store the ISBN-13 form as the canonical identifier
6. Step 4: Validate the ISSN
ISSN (International Standard Serial Number) identifies serial publications (journals, magazines, newspapers). It's 8 digits in two groups of four (XXXX-XXXX) with a MOD-11 check digit (0–9 or X).
Example response
{ "valid": true, "issn": "0378-5955", "normalized": "03785955" }
7. Putting it all together — parallel validation
The following example validates all applicable identifiers in parallel at article submission time. Pass only the identifiers that are present — the function adapts.
import { createClient } from '@isvalid-dev/sdk'; const iv = createClient({ apiKey: process.env.ISVALID_API_KEY }); async function validateAcademicSubmission({ doi, // article DOI (optional — may not exist yet for new submissions) orcid, // author ORCID isbn, // for book chapters or book references issn, // journal ISSN }) { const calls = {}; if (doi) calls.doi = iv.doi(doi, { lookupMetadata: true }); if (orcid) calls.orcid = iv.orcid(orcid, { lookupProfile: true }); if (isbn) calls.isbn = iv.isbn(isbn); if (issn) calls.issn = iv.issn(issn); const keys = Object.keys(calls); const results = await Promise.all(Object.values(calls)); const validated = Object.fromEntries(keys.map((k, i) => [k, results[i]])); return { doi: validated.doi ? { valid: validated.doi.valid, url: validated.doi.url ?? null, title: validated.doi.metadata?.title ?? null, authors: validated.doi.metadata?.authors ?? null, } : null, orcid: validated.orcid ? { valid: validated.orcid.valid, uri: validated.orcid.uri ?? null, name: validated.orcid.profile ? `${validated.orcid.profile.givenNames} ${validated.orcid.profile.familyName}` : null, } : null, isbn: validated.isbn ? { valid: validated.isbn.valid, isbn13: validated.isbn.isbn13 ?? null, } : null, issn: validated.issn ? { valid: validated.issn.valid, issn: validated.issn.issn ?? null, } : null, }; } // ── Example: journal article submission ──────────────────────────────────── const result = await validateAcademicSubmission({ doi: '10.1038/nature12373', orcid: '0000-0002-1825-0097', issn: '0028-0836', // Nature journal ISSN }); console.log('DOI :', result.doi?.valid ? `✓ ${result.doi.url}` : '✗ invalid'); console.log('ORCID:', result.orcid?.valid ? `✓ ${result.orcid.name ?? '(private profile)'}` : '✗ invalid'); console.log('ISSN :', result.issn?.valid ? `✓ ${result.issn.issn}` : '✗ invalid'); // Use DOI metadata to pre-fill citation fields if (result.doi?.title) { console.log('Title (from CrossRef):', result.doi.title); }
lookupMetadata: true) to pre-fill article title and authors from CrossRef — reducing manual entry errors in the submission form.8. cURL examples
Validate a DOI with metadata lookup:
curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.isvalid.dev/v0/doi?value=10.1038/nature12373&lookup=true"
Validate an ORCID with profile lookup:
curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.isvalid.dev/v0/orcid?value=0000-0002-1825-0097&lookup=true"
Validate an ISBN:
curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.isvalid.dev/v0/isbn?value=9783161484100"
Validate an ISSN:
curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://api.isvalid.dev/v0/issn?value=0028-0836"
9. Handling edge cases
DOI valid but metadata not found
CrossRef doesn't index all DOIs. Preprints (arXiv, bioRxiv) and datasets often have valid DOIs with no CrossRef record. metadata.found: false is not an error.
if (doiResult.valid && !doiResult.metadata?.found) { // DOI format is valid but no CrossRef record // Store the DOI but don't try to pre-fill citation metadata console.log('DOI valid — no CrossRef metadata (may be preprint or dataset)'); }
ORCID profile not public — still valid
Researchers can make their ORCID profiles private. profile.found: false does not mean the ORCID is invalid — the format and checksum passed. Accept the ORCID.
if (orcidResult.valid && !orcidResult.profile?.found) { // ORCID is valid but profile is private // Accept the ORCID — do not reject the author author.orcid = orcidResult.uri; author.name = submittedName; // Use user-supplied name }
ISSN check character X
The ISSN check digit can be X (representing 10 in MOD-11). A user form might strip the X or convert to lowercase. Normalize before validating.
function normalizeISSN(raw) { // Uppercase, add hyphen if missing const clean = raw.toUpperCase().replace(/[^0-9X]/g, ''); if (clean.length === 8) return `${clean.slice(0,4)}-${clean.slice(4)}`; return raw; } const result = await iv.issn(normalizeISSN('03785955x')); // → '0378-595X'
10. Summary checklist
See also
Validate academic identifiers at submission
Free tier includes 100 API calls per day. DOI, ORCID, ISBN, and ISSN validation all included. No credit card required.