A Java client library for interacting with the DatabunkerPro API. DatabunkerPro is a secure, privacy-focused data vault that helps organizations manage and protect sensitive user data.
The client covers the full Databunker Pro API:
- User Management
- App Data Management
- File Storage
- Tokenization
- Legal Basis & Agreement Management
- Processing Activity Management
- Group Management
- Role & Policy Management
- Session Management
- Shared Records
- Bulk Operations
- Audit Management
- Tenant Management
- Authentication & Access Tokens
- System Operations
Java-specific:
- Typed options classes for better type safety
- Thread-safe implementation
- Comprehensive test suite
- Enhanced error handling
- Continuous security scanning (Semgrep SAST, pinned CI actions)
- Java 11 or higher
- Maven 3.6 or higher
Add the repository and dependency to your pom.xml:
<repositories>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/securitybunker/databunkerpro-java</url>
</repository>
</repositories>
<dependency>
<groupId>org.databunker</groupId>
<artifactId>databunkerpro-java</artifactId>
<version>1.1.0</version>
</dependency>Add the JitPack repository and dependency to your pom.xml:
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependency>
<groupId>com.github.securitybunker</groupId>
<artifactId>databunkerpro-java</artifactId>
<version>v1.1.0</version>
</dependency>Note: Replace v1.1.0 with your desired version tag (e.g., v1.1.1, v2.0.0, etc.)
For development or internal use:
# Clone and install locally
git clone https://github.com/securitybunker/databunkerpro-java.git
cd databunkerpro-java
mvn clean installThen add the dependency to your pom.xml:
<dependency>
<groupId>org.databunker</groupId>
<artifactId>databunkerpro-java</artifactId>
<version>1.1.1-SNAPSHOT</version>
</dependency>You need a Databunker Pro instance to talk to. Demo mode gives you one in a single command — no database, no configuration, everything held in memory:
docker run -p 3000:3000 -d --rm --name databunkerpro securitybunker/databunkerpro demoCheck that it came up:
docker logs databunkerpro Databunker Pro demo is ready
Web UI: http://localhost:3000/
Root access token: DEMO
Database: in-memory, erased on restart
The root access token in demo mode is the fixed string DEMO. Save this as Quickstart.java:
import org.databunker.DatabunkerproApi;
import org.databunker.options.FileOptions;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
public class Quickstart {
public static void main(String[] args) throws Exception {
DatabunkerproApi api = new DatabunkerproApi("http://localhost:3000", "DEMO", null);
// Create a user record. The vault encrypts the profile and returns a user token.
Map<String, Object> profile = new HashMap<>();
profile.put("email", "john@javatest.com");
profile.put("name", "John Doe");
profile.put("phone", "+15551234567");
Map<String, Object> created = api.createUser(profile, null, null);
System.out.println("User token: " + created.get("token"));
// Read the record back by any indexed field: token, login, email, phone, custom.
Map<String, Object> user = api.getUser("email", "john@javatest.com", null);
System.out.println("Profile: " + user.get("profile"));
// Store an encrypted file against that user, tagged by document type.
String filedata = Base64.getEncoder()
.encodeToString("fake passport scan bytes".getBytes());
FileOptions options = FileOptions.builder()
.tags(Arrays.asList("passport", "kyc"))
.build();
Map<String, Object> file = api.createFile(
"email", "john@javatest.com", "passport.jpg", filedata, options, null);
System.out.println("File uuid: " + file.get("fileuuid") + " | tags: " + file.get("tags"));
// List the user's files, filtered by tag.
Map<String, Object> listing = api.listUserFiles("email", "john@javatest.com", "kyc", null);
System.out.println("Files tagged kyc: " + listing.get("files"));
// Fetch the file back. Content returns base64-encoded in filedata.
Map<String, Object> fetched = api.getFile(
"email", "john@javatest.com", (String) file.get("fileuuid"), null);
byte[] bytes = Base64.getDecoder().decode((String) fetched.get("filedata"));
System.out.println("Decrypted: " + new String(bytes));
// Delete user record.
api.deleteUser("email", "john@javatest.com", null);
System.out.println("User deleted");
}
}mvn compile exec:java -Dexec.mainClass=QuickstartUser token: 91db0180-829d-9e9d-000a-e6975c746366
Profile: {email=john@javatest.com, name=John Doe, phone=+15551234567}
File uuid: 94e13382-b117-2a6e-ac2f-edc8ae2fb743 | tags: [kyc, passport]
Files tagged kyc: [{filename=passport.jpg, fileuuid=94e13382-b117-2a6e-ac2f-edc8ae2fb743, tags=[kyc, passport], ...}]
Decrypted: fake passport scan bytes
User deleted
Every method takes its optional arguments explicitly, since Java has no default parameters — pass null for the options and request-metadata parameters when you do not need them. Tags are lowercased, de-duplicated and sorted on write, which is why they come back in a different order than they were sent.
When you are done, stop the instance. It was started with --rm, so the container and its in-memory database are discarded:
docker stop databunkerproDemo mode is for evaluation only. The database is in memory, the wrapping key is a fixed public value, and the root token is the well-known string
DEMO. Never point it at real personal data. For a real deployment see the installation guide.
- File API: Store, retrieve, list, retag and delete encrypted per-user files
(
createFile,getFile,listUserFiles,replaceFileTags,deleteFile), plusbulkListFilesByTagfor bulk lookups. Options are passed with the typedFileOptionsbuilder (mimetype, tags,finaltime,slidingtime). - Apache HttpClient 5: Migrated off end-of-life HttpClient 4.x. If your project pins
HttpClient transitively, it now resolves
org.apache.httpcomponents.client5:httpclient5. - Removed internal portal endpoints:
preloginUser,loginUser,createCaptcha,getUIConfandgetTenantConfwere internal to the DatabunkerPro web portal and are no longer part of the client.
- Wrapping Key Generation: Generate wrapping keys from Shamir's Secret Sharing keys
- Typed Patch Operations: Use structured
PatchOperationobjects for user updates - Bulk Token Operations: Create multiple tokens efficiently with typed options
- Bulk User Deletion: Delete multiple users efficiently in a single operation
- License Key Management: Set system license keys for enhanced functionality
- Shared Record Management: Create and retrieve shared records with partner organizations
- Better HTTP status code handling
- Enhanced error messages and logging
- Graceful handling of API errors
- Structured patch operations with
PatchOperationclass - Builder pattern for complex options
- Enhanced error handling
import org.databunker.DatabunkerproApi;
// Initialize the API client
String apiUrl = "https://pro.databunker.org";
String apiToken = "your-api-token";
String tenantName = "your-tenant-name";
try (DatabunkerproApi api = new DatabunkerproApi(apiUrl, apiToken, tenantName)) {
// Use the API client
}// Create a user
Map<String, Object> profile = new HashMap<>();
profile.put("email", "user@example.com");
profile.put("name", "John Doe");
profile.put("phone", "+1234567890");
Map<String, Object> result = api.createUser(profile, null, null);
System.out.println("Created user with token: " + result.get("token"));
// Get a user
Map<String, Object> user = api.getUser("email", "user@example.com", null);
System.out.println("User profile: " + user.get("profile"));
// Update a user
Map<String, Object> updates = new HashMap<>();
updates.put("name", "John Smith");
api.updateUser("email", "user@example.com", updates, null);
// Delete a user
api.deleteUser("email", "user@example.com", null);
// Patch a user with typed operations
PatchOperation[] patchOps = {
new PatchOperation("replace", "/profile/name", "Jane Doe"),
new PatchOperation("add", "/profile/age", 25)
};
Map<String, Object> patchResult = api.patchUser("email", "user@example.com", patchOps, null);// Create app data
Map<String, Object> data = new HashMap<>();
data.put("key", "value");
api.createAppData("email", "user@example.com", "appname", data, null);
// Get app data
Map<String, Object> appData = api.getAppData("email", "user@example.com", "appname", null);// Store a file. The content is passed base64-encoded.
String filedata = Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get("passport.pdf")));
FileOptions fileOptions = FileOptions.builder()
.mimetype("application/pdf")
.tags(Arrays.asList("kyc", "passport"))
.finaltime("365d")
.build();
Map<String, Object> created = api.createFile("email", "user@example.com", "passport.pdf", filedata, fileOptions, null);
String fileuuid = (String) created.get("fileuuid");
// Get a file by uuid
Map<String, Object> file = api.getFile("email", "user@example.com", fileuuid, null);
// Get a file by name (the newest match is returned)
Map<String, Object> byName = api.getFile("email", "user@example.com", null, "passport.pdf", false, null);
// List the metadata of a user's files, optionally filtered by a single tag
Map<String, Object> allFiles = api.listUserFiles("email", "user@example.com", null);
Map<String, Object> kycFiles = api.listUserFiles("email", "user@example.com", "kyc", null);
// Replace the complete tag set on a file
api.replaceFileTags("email", "user@example.com", fileuuid, Arrays.asList("kyc", "verified"), null);
// Delete a file
api.deleteFile("email", "user@example.com", fileuuid, null);Tags are lowercased and de-duplicated by the server, must match ^[a-z0-9][a-z0-9._-]{0,49}$,
and at most 16 are kept per file.
// Get system statistics
Map<String, Object> stats = api.getSystemStats(null);
System.out.println("System statistics: " + stats.get("stats"));
// Generate wrapping key from Shamir's Secret Sharing keys
Map<String, Object> wrappingKey = api.generateWrappingKey("key1", "key2", "key3", null);
System.out.println("Generated wrapping key: " + wrappingKey.get("wrappingkey"));
// Get system metrics
Map<String, Object> metrics = api.getSystemMetrics(null);
System.out.println("System metrics: " + metrics);
// Set system license key
Map<String, Object> licenseResult = api.setLicenseKey("your-license-key", null);
System.out.println("License key setting result: " + licenseResult.get("status"));// Create a single token
TokenOptions tokenOptions = TokenOptions.builder()
.slidingtime("1d")
.finaltime("10d")
.unique(true)
.build();
Map<String, Object> token = api.createToken("creditcard", "1234567890", tokenOptions, null);
// Create multiple tokens in bulk
Map<String, Object>[] tokenRecords = new Map[2];
tokenRecords[0] = new HashMap<>();
tokenRecords[0].put("tokentype", "creditcard");
tokenRecords[0].put("record", "1234567890");
tokenRecords[1] = new HashMap<>();
tokenRecords[1].put("tokentype", "email");
tokenRecords[1].put("record", "user@example.com");
Map<String, Object> bulkTokens = api.createTokensBulk(tokenRecords, tokenOptions, null);// Create a shared record
SharedRecordOptions sharedOptions = SharedRecordOptions.builder()
.fields("name,email")
.partner("partner-org")
.appname("myapp")
.finaltime("100d")
.build();
Map<String, Object> sharedRecord = api.createSharedRecord("email", "user@example.com", sharedOptions, null);
// Get a shared record
Map<String, Object> retrievedRecord = api.getSharedRecord("record-uuid", null);To run the tests use the following command:
mvn testThe project supports deployment to both GitHub Packages and JitPack.
The project includes a GitHub Actions workflow that automatically:
- Builds the project on push to main branch
- Runs tests
- Deploys to GitHub Packages when triggered
To deploy:
- Go to Actions tab in your GitHub repository
- Select "Build java API" workflow
- Click "Run workflow"
- Set "Deploy to GitHub Packages" to true
- Click "Run workflow"
JitPack automatically builds and publishes your GitHub repository as a Maven dependency.
-
Create a Git tag for your release:
git tag v1.1.0 git push origin v1.1.0
-
JitPack automatically builds and publishes the package
-
Check build status at: https://jitpack.io/#securitybunker/databunkerpro-java
This library is scanned on every push and pull request, with a weekly scheduled sweep to catch drift:
- SAST (Semgrep): static analysis using the
p/java,p/secrets,p/security-audit, andp/owasp-top-tenrulesets. A finding fails the check, and results are published to the repository's Code Scanning tab. See.github/workflows/semgrep.yml. - Supply-chain hardening: every GitHub Action is pinned to a full commit SHA, so a mutable tag (
@v4) cannot be silently repointed to malicious code.
Reproduce the SAST scan locally:
pip install semgrep
semgrep scan \
--config p/java \
--config p/secrets \
--config p/security-audit \
--config p/owasp-top-tenTo report a security vulnerability, please email hello@databunker.org rather than opening a public issue.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
For support, please contact us at:
- Email: hello@databunker.org
- Website: https://databunker.org
- GitHub Issues: https://github.com/securitybunker/databunkerpro-java/issues