Official Java SDK for the Livepasses API - generate, manage, and redeem Apple Wallet and Google Wallet passes.
implementation("com.livepasses:livepasses-java:0.1.0")implementation 'com.livepasses:livepasses-java:0.1.0'<dependency>
<groupId>com.livepasses</groupId>
<artifactId>livepasses-java</artifactId>
<version>0.1.0</version>
</dependency>Requires Java 11+. Single runtime dependency: Jackson (jackson-databind).
import com.livepasses.sdk.Livepasses;
import com.livepasses.sdk.types.*;
Livepasses client = new Livepasses("lp_api_key_...");
PassGenerationResult result = client.passes().generate(
GeneratePassesParams.builder()
.templateId("your-template-id")
.passes(List.of(
PassRecipient.builder()
.customer(CustomerInfo.builder()
.firstName("Jane").lastName("Doe").email("jane@example.com").build())
.businessData(BusinessData.builder()
.sectionInfo("A").rowInfo("12").seatNumber("5").build())
.build()
))
.build()
);
System.out.println(result.getPasses().get(0).getPlatforms().getApple().getAddToWalletUrl());Pass your API key when creating the client. Get your key at dashboard.livepasses.com/api-keys.
Livepasses client = new Livepasses("lp_api_key_...",
LivepassesOptions.builder()
.baseUrl("https://api.livepasses.com") // default
.timeout(Duration.ofSeconds(30)) // default
.maxRetries(3) // default
.build());PassGenerationResult result = client.passes().generate(
GeneratePassesParams.builder()
.templateId("template-id")
.businessContext(BusinessContext.builder()
.event(EventContext.builder()
.eventName("Summer Concert 2026")
.eventDate("2026-07-15T18:00:00Z")
.build())
.build())
.passes(List.of(
PassRecipient.builder()
.customer(CustomerInfo.builder()
.firstName("Jane").lastName("Doe").email("jane@example.com").build())
.businessData(BusinessData.builder()
.sectionInfo("VIP").rowInfo("A").seatNumber("12")
.ticketType("VIP").price(150.0).currency("USD")
.build())
.build()
))
.options(PassGenerationOptions.builder().deliveryMethod("email").build())
.build()
);For multiple recipients, generateAndWait automatically polls until the batch completes:
PassGenerationResult result = client.passes().generateAndWait(
GeneratePassesParams.builder()
.templateId("template-id")
.passes(recipients)
.build(),
GenerateAndWaitOptions.builder()
.pollIntervalMs(2000) // 2s between polls (default)
.onProgress(status ->
System.out.printf("%.0f%% complete%n", status.getProgressPercentage()))
.build()
);If you need more control over polling, use generate + getBatchStatus:
PassGenerationResult initial = client.passes().generate(
GeneratePassesParams.builder()
.templateId("template-id")
.passes(recipients)
.build()
);
if (initial.getBatchOperation() != null) {
String batchId = initial.getBatchOperation().getBatchId();
BatchStatusResult status = client.passes().getBatchStatus(batchId);
while (!status.isCompleted()) {
Thread.sleep(2000);
status = client.passes().getBatchStatus(batchId);
System.out.printf("Progress: %.0f%%%n", status.getProgressPercentage());
}
System.out.printf("Completed: %d successful, %d failed%n",
status.getStatistics().getSuccessful(), status.getStatistics().getFailed());
}PassLookupResult pass = client.passes().lookup(
LookupPassParams.builder().passId("pass-id").build());
// or by pass number
PassLookupResult pass = client.passes().lookup(
LookupPassParams.builder().passNumber("LP-001").build());PassValidationResult validation = client.passes().validate("pass-id");
if (validation.isCanBeRedeemed()) {
// proceed with redemption
}// Generic redemption
PassRedemptionResult result = client.passes().redeem("pass-id", null);
// Event check-in with location
PassRedemptionResult result = client.passes().checkIn("pass-id",
CheckInParams.builder()
.location(RedemptionLocation.builder()
.name("Gate 1").latitude(40.71).longitude(-74.00).build())
.build());
// Coupon redemption with notes
PassRedemptionResult result = client.passes().redeemCoupon("pass-id",
RedeemCouponParams.builder()
.location(RedemptionLocation.builder().name("Store #42").build())
.notes("Applied to order #12345")
.build());Update business data or context on an existing pass:
client.passes().update("pass-id",
UpdatePassParams.builder()
.businessData(BusinessData.builder()
.currentPoints(750).memberTier("Platinum").build())
.businessContext(BusinessContext.builder()
.loyalty(LoyaltyContext.builder()
.programUpdate("Congratulations on reaching Platinum!").build())
.build())
.build());Update multiple passes at once:
client.passes().bulkUpdate(
BulkUpdatePassesParams.builder()
.passIds(List.of("pass-1", "pass-2", "pass-3"))
.businessData(BusinessData.builder().memberTier("Gold").build())
.businessContext(BusinessContext.builder()
.loyalty(LoyaltyContext.builder()
.seasonalMessage("Happy holidays from our team!").build())
.build())
.build());client.passes().generate(
GeneratePassesParams.builder()
.templateId("event-template-id")
.businessContext(BusinessContext.builder()
.event(EventContext.builder()
.eventName("Concert").eventDate("2026-07-15T18:00:00Z")
.doorsOpen("2026-07-15T16:00:00Z").build())
.build())
.passes(List.of(
PassRecipient.builder()
.customer(CustomerInfo.builder().firstName("Jane").lastName("Doe").build())
.businessData(BusinessData.builder()
.sectionInfo("A").rowInfo("1").seatNumber("5").gateInfo("North").build())
.build()
))
.build()
);client.passes().generate(
GeneratePassesParams.builder()
.templateId("loyalty-template-id")
.passes(List.of(
PassRecipient.builder()
.customer(CustomerInfo.builder()
.firstName("Jane").lastName("Doe").email("jane@example.com").build())
.businessData(BusinessData.builder()
.membershipNumber("MEM-001").currentPoints(500).memberTier("Gold").build())
.build()
))
.build()
);
// Earn points
client.passes().loyaltyTransact("pass-id",
LoyaltyTransactionParams.builder()
.transactionType("earn").points(100).description("Purchase reward").build());
// Spend points
client.passes().loyaltyTransact("pass-id",
LoyaltyTransactionParams.builder()
.transactionType("spend").points(50).description("Redeemed: Free coffee").build());client.passes().generate(
GeneratePassesParams.builder()
.templateId("coupon-template-id")
.businessContext(BusinessContext.builder()
.coupon(CouponContext.builder()
.campaignName("Summer Sale").specialMessage("20% off!")
.promotionStartDate("2026-06-01").promotionEndDate("2026-08-31").build())
.build())
.passes(List.of(
PassRecipient.builder()
.customer(CustomerInfo.builder().firstName("Jane").lastName("Doe").build())
.businessData(BusinessData.builder()
.promoCode("SUMMER20").maxUsageCount(1).build())
.build()
))
.build()
);// List templates
PagedResponse<TemplateListItem> templates = client.templates().list(
ListTemplatesParams.builder().status("Active").build());
// Get template details
TemplateDetail template = client.templates().get("template-id");TemplateDetail template = client.templates().create(
CreateTemplateParams.builder()
.name("VIP Event Pass")
.description("Premium event ticket template")
.businessFeatures(Map.of(
"passType", "event",
"hasSeating", true,
"supportedPlatforms", List.of("apple", "google")
))
.build());
System.out.printf("Created: %s — %s%n", template.getId(), template.getName());TemplateDetail updated = client.templates().update("template-id",
UpdateTemplateParams.builder()
.name("VIP Event Pass v2")
.description("Updated premium event ticket template")
.build());client.templates().activate("template-id");
client.templates().deactivate("template-id");// Register a webhook
Webhook webhook = client.webhooks().create(
CreateWebhookParams.builder()
.url("https://your-app.com/webhooks/livepasses")
.events(List.of(
WebhookEventType.PASS_GENERATED,
WebhookEventType.PASS_REDEEMED,
WebhookEventType.BATCH_COMPLETED))
.build());
System.out.println("Secret: " + webhook.getSecret()); // use to verify signatures
// List webhooks
List<Webhook> webhooks = client.webhooks().list();
// Remove a webhook
client.webhooks().delete("webhook-id");All errors extend LivepassesException (unchecked) for precise catch handling:
import com.livepasses.sdk.exceptions.*;
try {
client.passes().generate(params);
} catch (AuthenticationException e) {
System.err.println("Invalid API key");
} catch (ValidationException e) {
System.err.println("Invalid input: " + e.getMessage() + " " + e.getDetails());
} catch (ForbiddenException e) {
System.err.println("Insufficient permissions: " + e.getMessage());
} catch (RateLimitException e) {
System.err.printf("Rate limited. Retry after %ds%n", e.getRetryAfter());
} catch (QuotaExceededException e) {
System.err.println("Monthly pass quota exceeded — upgrade your plan");
} catch (NotFoundException e) {
System.err.println("Template or pass not found");
} catch (BusinessRuleException e) {
System.err.println("Business rule: " + e.getMessage());
} catch (LivepassesException e) {
// Catch-all for any other API error
System.err.printf("API error [%s]: %s (HTTP %d)%n", e.getCode(), e.getMessage(), e.getStatus());
}Use ApiErrorCodes for programmatic error code comparisons:
import com.livepasses.sdk.types.ApiErrorCodes;
try {
client.passes().redeem("pass-id", null);
} catch (LivepassesException e) {
switch (e.getCode()) {
case ApiErrorCodes.PASS_ALREADY_USED:
System.err.println("This pass has already been redeemed");
break;
case ApiErrorCodes.PASS_EXPIRED:
System.err.println("This pass has expired");
break;
case ApiErrorCodes.TEMPLATE_INACTIVE:
System.err.println("The template for this pass is inactive");
break;
default:
System.err.println("Unhandled error: " + e.getCode());
}
}| Exception | HTTP Status | When |
|---|---|---|
AuthenticationException |
401 | Invalid, expired, or revoked API key |
ValidationException |
400 | Request validation failed |
ForbiddenException |
403 | Insufficient permissions |
NotFoundException |
404 | Resource not found |
RateLimitException |
429 | Rate limit exceeded |
QuotaExceededException |
403 | API quota or subscription limit exceeded |
BusinessRuleException |
422 | Business rule violation (pass expired, already used, etc.) |
PagedResponse<GlobalPassDto> page1 = client.passes().list(
ListPassesParams.builder().page(1).pageSize(50).build());
System.out.printf("Page 1 of %d (%d total)%n",
page1.getPagination().getTotalPages(), page1.getPagination().getTotalItems());Iterator<GlobalPassDto> it = client.passes().listAutoPaginate(
ListPassesParams.builder().templateId("tpl-id").build());
while (it.hasNext()) {
GlobalPassDto pass = it.next();
System.out.println(pass.getId());
}
// Or use the Iterable helper for enhanced for-loops
for (GlobalPassDto pass : PaginationIterator.iterable(
page -> client.passes().list(ListPassesParams.builder().page(page).build()))) {
System.out.println(pass.getId());
}| Option | Default | Description |
|---|---|---|
baseUrl |
https://api.livepasses.com |
API base URL |
timeout |
Duration.ofSeconds(30) |
Request timeout |
maxRetries |
3 |
Max retries for failed requests (429, 5xx) |
The SDK automatically retries on:
- 429 Too Many Requests — honors
Retry-Afterheader - 5xx Server Errors — exponential backoff with jitter
See the examples/ directory for runnable classes:
- GeneratePassesExample.java — End-to-end pass generation, lookup, validation, and check-in
- LoyaltyWorkflowExample.java — Loyalty card lifecycle: generate, earn points, spend points, update tier
- CouponWorkflowExample.java — Coupon pass generation and redemption
- TemplateManagementExample.java — CRUD operations on pass templates
- WebhookSetupExample.java — Register, list, and manage webhooks
Run any example with:
export LIVEPASSES_API_KEY="your-api-key"
cd sdks/java
./gradlew run -PmainClass=com.livepasses.sdk.examples.GeneratePassesExamplecd sdks/java
./gradlew build # compile + test
./gradlew test # run tests only
./gradlew jar # produce JARMIT