Official Java SDK for integrating with Metrc RetailID.
Encode and decode RetailID QR labels to enable product traceability and supply chain visibility in your Java applications.
Each RetailID label encodes:
- A batch ID (12-byte identifier)
- An index (variable-length integer)
These are encoded as compact, URL-safe strings using either Base36 (uppercase) or Base64 (lowercase) format.
Add to your pom.xml:
<dependency>
<groupId>com.retailid</groupId>
<artifactId>retailid-sdk</artifactId>
<version>1.0.0</version>
</dependency>Add to your build.gradle:
dependencies {
implementation 'com.retailid:retailid-sdk:1.0.0'
}import com.retailid.*;
// Create a batch ID
ObjectId batchId = new ObjectId("ABCDEF012345670000027190");
// Encode as Base36 (default, uppercase)
EncodeOptions options = new EncodeOptions().setDomain("d.1a4.com");
String url = RetailId.encode(batchId, 485, options);
// Result: "HTTPS://D.1A4.COM/10NOIEYKAJDG6CF0EXGJL"
// Encode as Base64
EncodeOptions options = new EncodeOptions().setBase64(true).setDomain("d.1a4.com");
String urlBase64 = RetailId.encode(batchId, 485, options);
// Result: "https://d.1a4.com/q83vASNFZwAAAnGQ5QM"
// Custom domain
EncodeOptions customDomain = new EncodeOptions().setDomain("d.1a4.com");
String urlCustom = RetailId.encode(batchId, 485, customDomain);
// Result: "HTTPS://d.1a4.com/10NOIEYKAJDG6CF0EXGJL"import com.retailid.*;
// Decode a RetailID URL
RetailIdPair pair = RetailId.decode("HTTPS://D.1A4.COM/10NOIEYKAJDG6CF0EXGJL");
ObjectId batchId = pair.getBatchId();
int index = pair.getIndex();
System.out.println("Batch ID: " + batchId.toHexString()); // "ABCDEF012345670000027190"
System.out.println("Index: " + index); // 485import com.retailid.*;
// Construct from URL
RetailIdPair pair = new RetailIdPair("HTTPS://D.1A4.COM/10NOIEYKAJDG6CF0EXGJL");
// Access properties
ObjectId batchId = pair.getBatchId();
int index = pair.getIndex();
// Encode back to URL
String url = pair.encode();
// Encode with options
EncodeOptions options = new EncodeOptions().setBase64(true);
String urlBase64 = pair.encode(options);Main API for encoding and decoding RetailID URLs.
-
static String encode(ObjectId batchId, int index)- Encodes a RetailID to a URL string with default options (base36, 1a4.com)
-
static String encode(ObjectId batchId, int index, EncodeOptions options)- Encodes a RetailID to a URL string with custom options
-
static RetailIdPair decode(String url)- Decodes a RetailID URL string to a RetailIdPair
Represents a decoded RetailID.
-
RetailIdPair(String url)- Constructs by parsing a URL
-
RetailIdPair(ObjectId batchId, int index)- Constructs from batch ID and index
ObjectId getBatchId()- Returns the batch IDint getIndex()- Returns the package indexString encode()- Encodes to URL with default optionsString encode(EncodeOptions options)- Encodes with custom options
12-byte MongoDB ObjectId implementation.
ObjectId()- Generate random ObjectIdObjectId(String hexString)- From 24-char hex stringObjectId(byte[] bytes)- From 12-byte array
byte[] getId()- Returns the raw bytes (copy)String toHexString()- Converts to hex stringboolean equals(Object other)- Compare with ObjectId or byte array
Variable-length integer encoding (LEB128).
VarInt(int value)- Encode an integerVarInt(byte[] source)- Decode from bytes
static byte[] encode(int num)- Encode integer to bytesstatic DecodeResult decode(byte[] source)- Decode from bytesstatic DecodeResult decode(byte[] source, int offset)- Decode with offsetint getValue()- Get decoded valuebyte[] data()- Get encoded bytesint length()- Get byte length
Options for encoding RetailID URLs.
String getDomain()- Get the domain (default: "1a4.com")EncodeOptions setDomain(String domain)- Set custom domainboolean isBase64()- Check if using base64 (default: false)EncodeOptions setBase64(boolean base64)- Set encoding format
static String encode(byte[] bytes)- Encode to Base36static byte[] decode(String base36)- Decode from Base36static boolean isValid(String base36)- Check if valid Base36
static String encodeUrl64(String base64)- Convert to URL-safe Base64static String decodeUrl64(String encoded)- Convert from URL-safe Base64static String bytesToUrlBase64(byte[] bytes)- Encode bytes to URL Base64static byte[] urlBase64ToBytes(String urlBase64)- Decode URL Base64 to bytes
The SDK passes all test vectors from the JavaScript SDK:
| URL | Batch ID | Index |
|---|---|---|
HTTPS://1A4.COM/5LN8CBN1UB33DON9CHKX |
1a4060300020081000006609 |
1 |
HTTPS://1A4.COM/13TX7BMRX3IU01B9EGTPTT |
1a4060300020081000006609 |
128 |
HTTPS://1A4.COM/7V8S42PYJD1XC9C2UVNCD1D |
1a4060300020081000006609 |
16384 |
https://1a4.com/GkBgMAAEG2AAAJKXEQ |
1a40603000041b6000009297 |
17 |
# Compile
mvn compile
# Run tests
mvn test
# Package
mvn package
# Install to local repository
mvn install- Java 11 or higher
- Maven 3.6 or higher (for building)
- Zero external dependencies - Uses only Java standard library
- Feature parity with JavaScript SDK
- Comprehensive tests - Full JUnit 5 test suite
- Javadoc documentation - Complete API documentation
- Type-safe API - Leverages Java's type system
- Immutable objects - Thread-safe by design
- Uses characters: 0-9, A-Z
- Case-insensitive during decode
- Produces uppercase URLs
- Prefix:
HTTPS:// - Example:
HTTPS://D.1A4.COM/10NOIEYKAJDG6CF0EXGJL
- URL-safe Base64 (RFC 4648)
- Replaces
+with-and/with_ - Removes padding (
=) - Produces lowercase URLs
- Prefix:
https:// - Example:
https://1a4.com/GkBgMAAEG2AAAJKXEQ
All methods throw IllegalArgumentException for invalid inputs:
try {
RetailIdPair pair = RetailId.decode("invalid-url");
} catch (IllegalArgumentException e) {
System.err.println("Invalid RetailID URL: " + e.getMessage());
}MIT License - Copyright (c) 2025 Metrc LLC
Contributions welcome! Please ensure:
- All tests pass:
mvn test - Code follows Java conventions
- Javadoc is complete for public APIs
- Test vectors remain valid
For issues or questions:
- GitHub Issues: https://github.com/MetrcID/retailid/issues
- Email: dev@metrc.com