Python 3.8+ESM + CJSJava 11+.NET 6+Go 1.18+Ruby 2.7+

NDC Toolkit SDKs

Open-source, zero-dependency libraries for every major programming language. Convert between NDC10, NDC11, NDC12, and GTIN-14 formats with full step-by-step audit trails, smart format detection, and comprehensive test suites.

Zero Dependencies

Every SDK ships with no external runtime dependencies. Drop it into any project without dependency conflicts.

Never Throws on Bad Input

All conversion functions return typed result objects. Errors are data, not exceptions — except where idiomatic (Go errors, Ruby ArgumentError for check digit).

Full Conversion Surface

NDC10↔NDC11, NDC10↔NDC12, NDC11↔NDC12, NDC↔GTIN-14, GS1 check digit, NDC parsing, normalization, and smart auto-detect.

Step-by-Step Audit Trail

Every result includes a steps list explaining exactly how the conversion was performed — ideal for compliance and debugging.

Comprehensive Test Suites

Python: 46 tests · JS: 45 tests · Java: 30 tests · C#: 31 tests · Go: 35 tests · Ruby: 40 tests. All passing.

Smart Format Detection

Pass any NDC or GTIN-14 string to smartConvert — the SDK auto-detects the format and returns all applicable conversions in one call.

Python

Python 3.8+
Install
pip install ndc-toolkit
Import
from ndc_toolkit import ndc10_to_ndc11, ndc10_to_ndc12, ndc11_to_ndc12, ndc10_to_gtin14, gtin14_to_ndc10, calculate_gs1_check_digit, smart_convert, parse_ndc, normalize_ndc, detect_ndc_format
Result Types
ConversionsConversionResult
GTIN-14GtinResult
ParseParseResult
Notes
  • Requires Python 3.8 or later. No external dependencies.
  • All functions return dataclass result objects — never raise exceptions on bad input.
  • Format auto-detection works on hyphenated NDC10 strings (e.g., 4-4-2, 5-3-2, 5-4-1).
  • 10-digit NDCs without hyphens are flagged as ambiguous; use hyphenated form or FDA lookup.
from ndc_toolkit import ndc10_to_ndc11, ndc10_to_ndc12, ndc11_to_ndc12, ndc10_to_gtin14, calculate_gs1_check_digit

# NDC10 (4-4-2) → NDC11
r = ndc10_to_ndc11("0591-0369-01")
print(r.value)    # "00591-0369-01"
print(r.display)  # "00591-0369-01"

# NDC10 (4-4-2) → NDC12
r = ndc10_to_ndc12("0591-0369-01")
print(r.value)    # "000591036901"
print(r.display)  # "000591-0369-01"

# NDC11 → NDC12
r = ndc11_to_ndc12("00591-0369-01")
print(r.value)    # "000591036901"

# NDC10 → GTIN-14 (indicator digit 0, default)
g = ndc10_to_gtin14("0591-0369-01", indicator=0)
print(g.value)        # "00305910369013"
print(g.check_digit)  # 3

# GS1 check digit for a 13-digit payload
check = calculate_gs1_check_digit("0030591036901")
print(check)  # 3

NDC Format Reference

Understanding NDC formats is essential for using the SDK correctly. The FDA uses multiple NDC formats across different regulatory contexts.

NDC10

Legacy
Structure: Variable segment lengths
4-4-2 (labeler-product-package)
5-3-2 (labeler-product-package)
5-4-1 (labeler-product-package)
0591-0369-01

Legacy FDA format. Segment configuration must be known for accurate conversion. Always use hyphenated form.

NDC11 (HIPAA)

HIPAA Standard
Structure: 5-4-2 (fixed)
Always 5-digit labeler, 4-digit product, 2-digit package
00591-0369-01

HIPAA standard for claims. Produced by zero-padding the short segment of NDC10. Unambiguous format.

NDC12 (FDA Final Rule)

Effective 2033
Structure: 6-4-2 (fixed)
Always 6-digit labeler, 4-digit product, 2-digit package
000591-0369-01

FDA Final Rule (March 2026). Effective 2033. Legacy NDC12s have a leading zero on the labeler. New labeler codes (2033+) are natively 6 digits.

GTIN-14

GS1 Standard
Structure: [indicator] + 03 + [10-digit NDC] + [check]
14 digits total
GS1 '03' prefix for US pharmaceuticals
Indicator digit 0–8 (0 = unit of use)
00305910369013

GS1 standard for supply chain barcodes. Built from NDC10 digits (no hyphens) with a GS1 Mod-10 check digit appended.

Conversion Support Matrix

From → ToNDC11NDC12GTIN-14NDC10
NDC10 (hyphenated)
NDC11via NDC10 extractNot supported
NDC12Not supportedvia NDC10 extractNot supported
GTIN-14 (03 prefix)Not supportedNot supporteddigits only (ambiguous)

Full API Reference

All methods are available in every SDK. Names follow each language's conventions (snake_case for Python/Ruby, camelCase for JS/Java, PascalCase for C#, PascalCase for Go).

MethodInputOutputReturnsDescription
ndc10_to_ndc11 / ndc10ToNdc11 / Ndc10ToNdc11 / NDC10ToNDC11NDC10 (hyphenated) + format hint (4-4-2 / 5-3-2 / 5-4-1)NDC11 (5-4-2)ConversionResultPads the short labeler or package segment with a leading zero based on the original NDC10 configuration.
ndc10_to_ndc12 / ndc10ToNdc12 / Ndc10ToNdc12 / NDC10ToNDC12NDC10 (hyphenated) + format hintNDC12 (6-4-2)ConversionResultConverts NDC10 to NDC12 by chaining through NDC11. Pads labeler to 6 digits.
ndc11_to_ndc12 / ndc11ToNdc12 / Ndc11ToNdc12 / NDC11ToNDC12NDC11 (5-4-2, with or without dashes)NDC12 (6-4-2)ConversionResultPrepends a zero to the 5-digit labeler to produce the 6-digit labeler required by NDC12.
ndc12_to_ndc11 / ndc12ToNdc11 / Ndc12ToNdc11 / NDC12ToNDC11NDC12 (6-4-2)Always failsConversionResult (success=false)Not supported. The original NDC10 segment configuration is lost during NDC12 conversion. New 6-digit labeler codes (2033+) have no NDC11 equivalent.
ndc_to_gtin14 / ndc10ToGtin14 / NdcToGtin14 / NDCToGTIN14NDC (10/11/12 digits) + indicator digit (0–8)GTIN-14GtinResultBuilds GTIN-14: [indicator] + '03' + [10-digit NDC] + [GS1 Mod-10 check digit]. Accepts NDC10, NDC11, or NDC12.
gtin14_to_ndc10 / gtin14ToNdc10 / Gtin14ToNdc10 / GTIN14ToNDC10GTIN-14 (14 digits)10-digit NDC (digits only, no hyphens)ConversionResultExtracts the 10-digit NDC from a pharmaceutical GTIN-14 (GS1 '03' prefix). Result is ambiguous without hyphens — use FDA lookup to determine the original configuration.
calculate_gs1_check_digit / calculateGs1CheckDigit / CalculateGs1CheckDigit / CalculateGS1CheckDigit13-digit payload (string)Check digit (0–9)int / numberCalculates the GS1 Mod-10 (Luhn-variant) check digit for a 13-digit GTIN payload.
parse_ndc / parseNdc / ParseNdc / ParseNDCNDC string + optional format hint for NDC10Labeler, Product, Package, FormatParseResultSplits an NDC into its three component segments. For NDC10, a format hint (4-4-2, 5-3-2, or 5-4-1) is required. NDC11 and NDC12 are auto-parsed.
normalize_ndc / normalizeNdc / NormalizeNdc / NormalizeNDCNDC string (any format)Digit-only stringstringStrips dashes, spaces, and other non-digit characters from an NDC string.
smart_convert / smartConvert / SmartConvertAny NDC or GTIN-14 stringAll applicable conversionsSmartConversionResultAuto-detects the input format and returns all applicable conversions (NDC10, NDC11, NDC12, GTIN-14) in a single call. Flags ambiguous inputs with warnings.

Result Type Reference

ConversionResult
successbool

Whether the conversion succeeded.

valuestring | null

Digit-only result (no hyphens).

displaystring | null

Hyphenated display form.

errorstring | null

Human-readable error message on failure.

warningstring | null

Optional warning (e.g., unsupported reverse conversion).

stepsstring[]

Step-by-step conversion audit trail.

GtinResult
successbool

Whether the GTIN-14 was generated successfully.

valuestring | null

14-digit GTIN-14 string.

checkDigitint | null

GS1 Mod-10 check digit (0–9). -1 on failure.

explanationstring | null

Step-by-step explanation of GTIN construction.

errorstring | null

Human-readable error message on failure.

ParseResult
successbool

Whether parsing succeeded.

labelerstring | null

Labeler segment (4, 5, or 6 digits).

productstring | null

Product segment (3 or 4 digits).

packagestring | null

Package segment (1 or 2 digits).

formatstring | null

Detected format string (e.g., '4-4-2', '5-4-2', '6-4-2').

errorstring | null

Human-readable error message on failure.

Common Questions & Pitfalls

A 10-digit NDC without hyphens is structurally ambiguous. The same digit string could represent three different configurations: 4-4-2 (labeler-product-package), 5-3-2, or 5-4-1. The padding rule for converting to NDC11 or NDC12 depends on which segment is short.

Always use the hyphenated form of NDC10 (e.g., 0591-0369-01) — the SDK auto-detects the configuration from the hyphen positions. If you only have the digit string, use the FDA NDC Directory to look up the correct configuration.

All Repositories

PythonPython 3.8+
pip install ndc-toolkit
GitHub View docs
JavaScript / TypeScriptESM + CJS
npm install @lspedia/ndc-toolkit
GitHub View docs
JavaJava 11+
<!-- Maven -->
GitHub View docs
C# / .NET.NET 6+
dotnet add package LSPedia.NdcToolkit
GitHub View docs
GoGo 1.18+
go get github.com/lspedia/ndc-toolkit
GitHub View docs
RubyRuby 2.7+
gem install ndc_toolkit
GitHub View docs