Short answer
The Linkbreakers Java SDK enables programmatic link management, visitor identification, QR code generation, and analytics access from your Java backend applications. Install it with Maven or Gradle, authenticate with a secret API key, and start creating trackable links for your campaigns, products, or events.
Installation
Maven
Add the dependency to your pom.xml:
<dependency>
<groupId>com.linkbreakers</groupId>
<artifactId>linkbreakers-java</artifactId>
<version>1.0.0</version>
</dependency>
Gradle
Add the dependency to your build.gradle:
dependencies {
implementation 'com.linkbreakers:linkbreakers-java:1.0.0'
}
Or for Kotlin DSL (build.gradle.kts):
dependencies {
implementation("com.linkbreakers:linkbreakers-java:1.0.0")
}
Understanding API keys for Java
The Java SDK is designed for backend/server-side use only and requires a secret API key with full workspace access.
Secret keys
Backend-only. These JWT tokens grant full API access and must never be exposed in public repositories or client-side code.
What they allow:
- Create, update, and delete links
- Generate and customize QR codes
- Identify and track visitors
- Access analytics and metrics
- Manage workspace resources
- Full API access
Where to use:
- Spring Boot applications
- Jakarta EE / Java EE applications
- Microservices (Micronaut, Quarkus)
- Background jobs and schedulers
- CLI tools
- Enterprise applications
Security note: Java applications typically run on servers, making them perfect for secret key usage. Never log keys, commit them to git, or expose them in error messages.
Creating a secret API key
Create your API key from the dashboard:
- Log in to app.linkbreakers.com
- Navigate to Dashboard → API Tokens
- Click Create API Token
- Select Secret Key (full API access)
- Give it a descriptive name (e.g., "Production Backend" or "Java Service")
- Copy the generated JWT token immediately
Important: You won't see the key again after creation. Store it in environment variables or a secret management system (AWS Secrets Manager, HashiCorp Vault, etc.).
Quick start
Initialize the client and create your first shortened link:
package com.example.linkbreakers;
import com.linkbreakers.ApiClient;
import com.linkbreakers.ApiException;
import com.linkbreakers.Configuration;
import com.linkbreakers.api.LinksApi;
import com.linkbreakers.model.CreateLinkRequest;
import com.linkbreakers.model.CreateLinkResponse;
import java.util.Arrays;
public class QuickStart {
public static void main(String[] args) {
// Configure API client with your secret key
String apiKey = System.getenv("LINKBREAKERS_SECRET_KEY");
ApiClient apiClient = Configuration.getDefaultApiClient();
apiClient.setBasePath("https://api.linkbreakers.com");
apiClient.setBearerToken(apiKey);
LinksApi linksApi = new LinksApi(apiClient);
try {
// Create a shortened link
CreateLinkRequest request = new CreateLinkRequest()
.destination("https://example.com/product")
.name("Product Launch - Spring 2025")
.tags(Arrays.asList("marketing", "product-launch"));
CreateLinkResponse response = linksApi.linksServiceCreate(request);
System.out.println("Short URL: " + response.getLink().getShortlink());
System.out.println("Link ID: " + response.getLink().getId());
System.out.println("QR Code: " + response.getLink().getQrcodeSignedUrl());
} catch (ApiException e) {
System.err.println("API Error: " + e.getMessage());
e.printStackTrace();
}
}
}
Environment variables (best practice)
Never hardcode API keys. Use environment variables:
package com.example.linkbreakers;
import com.linkbreakers.ApiClient;
import com.linkbreakers.Configuration;
public class ApiClientFactory {
private static ApiClient apiClient;
public static ApiClient getClient() {
if (apiClient == null) {
String apiKey = System.getenv("LINKBREAKERS_SECRET_KEY");
apiClient = Configuration.getDefaultApiClient();
apiClient.setBasePath("https://api.linkbreakers.com");
apiClient.setBearerToken(apiKey);
}
return apiClient;
}
}
Set your environment variable:
# .env file or export directly
export LINKBREAKERS_SECRET_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3b3Jrc3BhY2VfaWQiOiIxMjM0IiwidHlwZSI6InNlY3JldCJ9...
Loading with Spring Boot (application.properties):
linkbreakers.secret-key=${LINKBREAKERS_SECRET_KEY}
@Value("${linkbreakers.secret-key}")
private String linkbreakersSecretKey;
Creating and managing links
Basic link creation
package com.example.linkbreakers;
import com.linkbreakers.ApiException;
import com.linkbreakers.api.LinksApi;
import com.linkbreakers.model.CreateLinkRequest;
import com.linkbreakers.model.CreateLinkResponse;
import java.util.Arrays;
public class LinkCreation {
public void createBasicLink(LinksApi linksApi) {
try {
CreateLinkRequest request = new CreateLinkRequest()
.destination("https://example.com/summer-sale")
.name("Summer Sale 2025")
.tags(Arrays.asList("campaign", "summer", "email"));
CreateLinkResponse response = linksApi.linksServiceCreate(request);
System.out.println("Created: " + response.getLink().getShortlink());
} catch (ApiException e) {
e.printStackTrace();
}
}
}
Advanced link options
package com.example.linkbreakers;
import com.linkbreakers.ApiException;
import com.linkbreakers.api.LinksApi;
import com.linkbreakers.model.CreateLinkRequest;
import com.linkbreakers.model.CreateLinkResponse;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class AdvancedLinkCreation {
public void createAdvancedLinks(LinksApi linksApi) {
try {
// Create link with custom shortlink
CreateLinkRequest customRequest = new CreateLinkRequest()
.destination("https://example.com/docs")
.shortlink("docs") // Creates lbr.ai/docs
.name("Documentation Portal")
.fallbackDestination("https://example.com/404")
.tags(Arrays.asList("internal", "docs"));
CreateLinkResponse customLink = linksApi.linksServiceCreate(customRequest);
// Create link with metadata for tracking
Map<String, String> metadata = new HashMap<>();
metadata.put("product_id", "123");
metadata.put("campaign_id", "spring-2025");
metadata.put("utm_source", "email");
metadata.put("utm_medium", "newsletter");
metadata.put("utm_campaign", "product-launch");
CreateLinkRequest trackedRequest = new CreateLinkRequest()
.destination("https://example.com/product/123")
.name("Product 123 - Email Campaign")
.metadata(metadata)
.tags(Arrays.asList("product", "email"));
CreateLinkResponse trackedLink = linksApi.linksServiceCreate(trackedRequest);
// Create link with QR code (wait for generation)
CreateLinkRequest qrRequest = new CreateLinkRequest()
.destination("https://example.com/event-registration")
.name("Conference 2025 Registration")
.waitForQrcode(true) // Blocks until QR is generated
.tags(Arrays.asList("event", "conference", "qr-code"));
CreateLinkResponse qrLink = linksApi.linksServiceCreate(qrRequest);
System.out.println("Download QR code: " + qrLink.getLink().getQrcodeSignedUrl());
} catch (ApiException e) {
e.printStackTrace();
}
}
}
Listing and filtering links
package com.example.linkbreakers;
import com.linkbreakers.ApiException;
import com.linkbreakers.api.LinksApi;
import com.linkbreakers.model.Link;
import com.linkbreakers.model.Linkbreakersv1LinksSortField;
import com.linkbreakers.model.Linkbreakersv1SortDirection;
import com.linkbreakers.model.ListLinksResponse;
import java.util.Arrays;
import java.util.List;
public class LinkListing {
public void listLinks(LinksApi linksApi) {
try {
ListLinksResponse response = linksApi.linksServiceList(
50, // pageSize
null, // pageToken
Arrays.asList("marketing", "email"), // tags
"campaign", // search
Linkbreakersv1LinksSortField.UPDATED_AT, // sortBy
Linkbreakersv1SortDirection.DESC, // sortDirection
null, // directoryId
null, // includeAllDirectories
null // include
);
List<Link> links = response.getLinks();
for (Link link : links) {
System.out.println(link.getName() + ": " + link.getShortlink());
System.out.println(" Tags: " + link.getTags());
System.out.println(" Created: " + link.getCreatedAt());
}
} catch (ApiException e) {
e.printStackTrace();
}
}
}
Updating and deleting links
package com.example.linkbreakers;
import com.linkbreakers.ApiException;
import com.linkbreakers.api.LinksApi;
import com.linkbreakers.model.GetLinkResponse;
import com.linkbreakers.model.UpdateLinkRequest;
import java.util.Arrays;
public class LinkManagement {
public void updateAndDeleteLink(LinksApi linksApi, String linkId) {
try {
// Get a specific link
GetLinkResponse linkResponse = linksApi.linksServiceGet(
linkId,
Arrays.asList("tags", "qrcodeSignedUrl")
);
// Update link
UpdateLinkRequest updateRequest = new UpdateLinkRequest()
.name("Updated Campaign Name")
.tags(Arrays.asList("marketing", "q2-2025", "updated"));
linksApi.linksServiceUpdate(linkId, updateRequest);
// Delete link
linksApi.linksServiceDelete(linkId);
} catch (ApiException e) {
e.printStackTrace();
}
}
}
Bulk link creation
Create hundreds of links efficiently in a single API call:
package com.example.linkbreakers;
import com.linkbreakers.ApiException;
import com.linkbreakers.api.LinksApi;
import com.linkbreakers.model.CreateBulkLinksRequest;
import com.linkbreakers.model.CreateBulkLinksResponse;
import com.linkbreakers.model.CreateLinkRequest;
import com.linkbreakers.model.Link;
import java.util.*;
class Product {
String id;
String name;
String url;
Product(String id, String name, String url) {
this.id = id;
this.name = name;
this.url = url;
}
}
public class BulkLinkCreation {
public void createBulkLinks(LinksApi linksApi) {
try {
// Prepare bulk links (e.g., from a product catalog)
List<Product> products = Arrays.asList(
new Product("001", "Widget A", "https://example.com/products/001"),
new Product("002", "Widget B", "https://example.com/products/002"),
new Product("003", "Widget C", "https://example.com/products/003")
);
List<CreateLinkRequest> linksToCreate = new ArrayList<>();
for (Product product : products) {
Map<String, String> metadata = new HashMap<>();
metadata.put("product_id", product.id);
metadata.put("sku", "SKU-" + product.id);
CreateLinkRequest request = new CreateLinkRequest()
.destination(product.url)
.name("Product: " + product.name)
.tags(Arrays.asList("product", "catalog"))
.metadata(metadata);
linksToCreate.add(request);
}
// Create all links in one request
CreateBulkLinksRequest bulkRequest = new CreateBulkLinksRequest()
.links(linksToCreate);
CreateBulkLinksResponse response = linksApi.linksServiceCreateBulk(bulkRequest);
System.out.println("Created " + response.getLinks().size() + " links");
for (Link link : response.getLinks()) {
System.out.println(" " + link.getName() + ": " + link.getShortlink());
}
} catch (ApiException e) {
e.printStackTrace();
}
}
}
When to use bulk creation:
- Importing product catalogs
- Generating links from database records
- Campaign setup with many URLs
- Automated link generation pipelines
Visitor identification and tracking
Track and identify visitors using their LBID (Linkbreakers ID) from click/scan events:
package com.example.linkbreakers;
import com.linkbreakers.ApiException;
import com.linkbreakers.api.VisitorsApi;
import com.linkbreakers.model.IdentifyRequest;
import com.linkbreakers.model.IdentifyResponse;
import com.linkbreakers.model.VisitorInput;
import java.util.HashMap;
import java.util.Map;
public class VisitorIdentification {
public void identifyVisitor(VisitorsApi visitorsApi, String lbid) {
try {
// Prepare visitor data
Map<String, Object> visitorData = new HashMap<>();
// System fields (prefixed with "$")
visitorData.put("$email", "john.doe@example.com");
visitorData.put("$phone", "+14155551234");
visitorData.put("$firstName", "John");
visitorData.put("$lastName", "Doe");
// Custom attributes (no "$" prefix)
visitorData.put("company", "Acme Corporation");
visitorData.put("jobTitle", "Product Manager");
visitorData.put("plan", "enterprise");
visitorData.put("signupDate", "2024-01-15");
visitorData.put("industry", "SaaS");
visitorData.put("leadScore", 85);
VisitorInput visitorInput = new VisitorInput()
.data(visitorData);
IdentifyRequest identifyRequest = new IdentifyRequest()
.lbid(lbid)
.visitor(visitorInput)
.setOnce(false); // true = only update empty fields
IdentifyResponse response = visitorsApi.visitorsServiceIdentify(identifyRequest);
System.out.println("New profile created: " + response.getCreated());
System.out.println("Visitor ID: " + response.getVisitor().getId());
System.out.println("Email: " + response.getVisitor().getEmail());
} catch (ApiException e) {
e.printStackTrace();
}
}
}
Understanding LBID:
When visitors click your Linkbreakers links with conversion tracking enabled, a ?lbid=... parameter is added to the destination URL. This LBID connects the visitor to the specific link click, enabling attribution and analytics.
Extract LBID from incoming requests and pass it to the identification API to build visitor profiles. Learn more in our What is LBID? guide.
Working with visitor data
package com.example.linkbreakers;
import com.linkbreakers.ApiException;
import com.linkbreakers.api.VisitorsApi;
import com.linkbreakers.model.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class VisitorDataManagement {
public void workWithVisitors(VisitorsApi visitorsApi, String visitorId) {
try {
// Get visitor details
GetVisitorResponse visitor = visitorsApi.visitorsServiceGet(
visitorId,
Arrays.asList("devices", "events", "links")
);
System.out.println("Visitor: " + visitor.getEmail());
System.out.println("Devices: " + (visitor.getDevices() != null ? visitor.getDevices().size() : 0));
System.out.println("Events: " + (visitor.getEvents() != null ? visitor.getEvents().size() : 0));
// List visitors with filtering
ListVisitorsResponse visitorsList = visitorsApi.visitorsServiceList(
100, // pageSize
null, // pageToken
"user@example.com", // email
"link-uuid", // linkId
"Acme Corp", // search
null, // include
null // responseFormat
);
// Update visitor attributes
Map<String, Object> updateData = new HashMap<>();
updateData.put("$email", "updated@example.com");
updateData.put("plan", "enterprise");
updateData.put("lastActivity", "2025-03-31");
VisitorInput visitorUpdate = new VisitorInput()
.data(updateData);
VisitorsServiceUpdateBody updateBody = new VisitorsServiceUpdateBody()
.visitor(visitorUpdate);
visitorsApi.visitorsServiceUpdate(visitorId, updateBody);
} catch (ApiException e) {
e.printStackTrace();
}
}
}
Accessing analytics and metrics
Retrieve event data and workspace metrics:
package com.example.linkbreakers;
import com.linkbreakers.ApiException;
import com.linkbreakers.api.EventsApi;
import com.linkbreakers.api.MetricsApi;
import com.linkbreakers.model.Event;
import com.linkbreakers.model.GetWorkspaceMetricsResponse;
import com.linkbreakers.model.ListEventsResponse;
import java.time.OffsetDateTime;
import java.util.Arrays;
public class Analytics {
public void getAnalytics(EventsApi eventsApi, MetricsApi metricsApi, String linkId) {
try {
// Get events for a specific link (last 30 days)
OffsetDateTime endDate = OffsetDateTime.now();
OffsetDateTime startDate = endDate.minusDays(30);
ListEventsResponse eventsResponse = eventsApi.eventsServiceList(
startDate, // startDate
endDate, // endDate
1000, // pageSize
null, // pageToken
linkId, // linkId
Arrays.asList("visitor", "device", "link"), // include
null // responseFormat
);
System.out.println("Total events: " + eventsResponse.getEvents().size());
int count = 0;
for (Event event : eventsResponse.getEvents()) {
if (count >= 10) break;
System.out.println(" " + event.getAction() + " - " + event.getCreatedAt());
count++;
}
// Get workspace metrics
GetWorkspaceMetricsResponse metrics = metricsApi.metricsServiceGetWorkspaceMetrics();
System.out.println("\nWorkspace Stats:");
System.out.println(" Total links: " + metrics.getTotalLinks());
System.out.println(" Total clicks: " + metrics.getTotalClicks());
System.out.println(" Total visitors: " + metrics.getTotalVisitors());
} catch (ApiException e) {
e.printStackTrace();
}
}
}
Framework integration
Spring Boot
Configuration class:
package com.example.linkbreakers.config;
import com.linkbreakers.ApiClient;
import com.linkbreakers.Configuration;
import com.linkbreakers.api.LinksApi;
import com.linkbreakers.api.VisitorsApi;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
@org.springframework.context.annotation.Configuration
public class LinkbreakersConfig {
@Value("${linkbreakers.secret-key}")
private String secretKey;
@Bean
public ApiClient apiClient() {
ApiClient apiClient = Configuration.getDefaultApiClient();
apiClient.setBasePath("https://api.linkbreakers.com");
apiClient.setBearerToken(secretKey);
return apiClient;
}
@Bean
public LinksApi linksApi(ApiClient apiClient) {
return new LinksApi(apiClient);
}
@Bean
public VisitorsApi visitorsApi(ApiClient apiClient) {
return new VisitorsApi(apiClient);
}
}
Controller example:
package com.example.linkbreakers.controller;
import com.linkbreakers.ApiException;
import com.linkbreakers.api.LinksApi;
import com.linkbreakers.model.CreateLinkRequest;
import com.linkbreakers.model.CreateLinkResponse;
import com.linkbreakers.model.ListLinksResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class LinksController {
@Autowired
private LinksApi linksApi;
@PostMapping("/create-link")
public ResponseEntity<Map<String, Object>> createLink(@RequestBody CreateLinkRequestDto dto) {
try {
CreateLinkRequest request = new CreateLinkRequest()
.destination(dto.getDestination())
.name(dto.getName())
.tags(dto.getTags());
CreateLinkResponse response = linksApi.linksServiceCreate(request);
Map<String, Object> result = new HashMap<>();
result.put("success", true);
result.put("shortlink", response.getLink().getShortlink());
result.put("qr_code", response.getLink().getQrcodeSignedUrl());
return ResponseEntity.ok(result);
} catch (ApiException e) {
Map<String, Object> error = new HashMap<>();
error.put("success", false);
error.put("error", e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}
@GetMapping("/links")
public ResponseEntity<?> listLinks(@RequestParam(required = false) List<String> tags) {
try {
ListLinksResponse response = linksApi.linksServiceList(
50, null, tags, null, null, null, null, null, null
);
return ResponseEntity.ok(response.getLinks());
} catch (ApiException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of("error", e.getMessage()));
}
}
}
class CreateLinkRequestDto {
private String destination;
private String name;
private List<String> tags;
// Getters and setters
public String getDestination() { return destination; }
public void setDestination(String destination) { this.destination = destination; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public List<String> getTags() { return tags; }
public void setTags(List<String> tags) { this.tags = tags; }
}
Service class pattern:
package com.example.linkbreakers.service;
import com.linkbreakers.ApiException;
import com.linkbreakers.api.LinksApi;
import com.linkbreakers.model.CreateLinkRequest;
import com.linkbreakers.model.Link;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class LinkService {
@Autowired
private LinksApi linksApi;
public Link createShortLink(String destination, String name) throws ApiException {
CreateLinkRequest request = new CreateLinkRequest()
.destination(destination)
.name(name);
return linksApi.linksServiceCreate(request).getLink();
}
}
Error handling
Implement proper error handling for production:
package com.example.linkbreakers;
import com.linkbreakers.ApiException;
import com.linkbreakers.api.LinksApi;
import com.linkbreakers.model.CreateLinkRequest;
import com.linkbreakers.model.CreateLinkResponse;
public class ErrorHandling {
public void createLinkWithErrorHandling(LinksApi linksApi) {
try {
CreateLinkRequest request = new CreateLinkRequest()
.destination("https://example.com/page")
.name("My Link");
CreateLinkResponse response = linksApi.linksServiceCreate(request);
System.out.println("Success: " + response.getLink().getShortlink());
} catch (ApiException e) {
System.err.println("API Error: Status " + e.getCode());
System.err.println("Response body: " + e.getResponseBody());
e.printStackTrace();
}
}
}
Frequently asked questions
Can I use the Java SDK with Spring Boot?
Yes! The SDK works seamlessly with Spring Boot, Jakarta EE, Micronaut, Quarkus, and any Java framework. See the Spring Boot integration section above.
How do I handle rate limits?
The SDK will throw ApiException if you exceed rate limits. Implement exponential backoff retry logic for production applications.
Does the SDK support async operations?
The SDK uses synchronous HTTP calls. For async frameworks like Spring WebFlux, wrap SDK calls in reactive publishers or use thread pools.
How do I get the LBID for visitor identification?
The LBID appears as a ?lbid= query parameter when visitors click your links with conversion tracking enabled. Extract it from request parameters and pass it to visitorsServiceIdentify().
Can I create bulk links efficiently?
Yes, use linksServiceCreateBulk() to create up to 1000 links in a single API call, which is much more efficient than individual requests.
What Java versions are supported?
The SDK supports Java 8+ with full support for modern Java features including records, var, and functional programming patterns.
How do I test without affecting production data?
Create test mode API keys from your dashboard. They operate on isolated test data separate from production analytics. You can identify test vs production keys by decoding the JWT and checking the environment claim.
Sources
Last reviewed
This article was last reviewed on March 31, 2025.
About the Author
Laurent Schaffner
Founder & Engineer at Linkbreakers
Passionate about building tools that help businesses track and optimize their digital marketing efforts. Laurent founded Linkbreakers to make QR code analytics accessible and actionable for companies of all sizes.
Related Articles
How to use the Linkbreakers API
Complete guide to integrating with the Linkbreakers API - create QR codes, manage links, customize designs, track analytics, and automate workflows programmatically.
Analytics API
Access comprehensive QR code and visitor analytics through the Linkbreakers API. Learn how to retrieve campaign performance data, visitor insights, and engagement metrics programmatically for business intelligence integration.
How to integrate Linkbreakers with existing tech stack
Integrate Linkbreakers with your CRM, marketing automation, analytics platforms, and business systems through APIs, webhooks, and direct integrations. Learn best practices for seamless tech stack integration.
On this page
Need more help?
Can't find what you're looking for? Get in touch with our support team.
Contact Support