Webhooks Management API
The Webhooks Management API v1 enables you to configure and manage webhook notifications for PayPal events.
Official Documentation: PayPal Webhooks API v1
Installation
Add the Webhooks API dependency to your project:
Creating the Client
import io.github.eealba.payper.webhooks.v1.api.WebhooksApiClient;
public class Example {
public static void main(String[] args) {
// Create client (uses environment variables for credentials)
var client = WebhooksApiClient.create();
// Access the webhooks API
var webhooksApi = client.webhooks();
}
}
Common Operations
Create a Webhook
Register a webhook endpoint to receive event notifications:
import io.github.eealba.payper.webhooks.v1.api.WebhooksApiClient;
import io.github.eealba.payper.webhooks.v1.model.*;
import java.util.List;
public class CreateWebhookExample {
public static void main(String[] args) {
var client = WebhooksApiClient.create();
// Define event types to subscribe to
var eventTypes = List.of(
EventType.builder().name("PAYMENT.CAPTURE.COMPLETED").build(),
EventType.builder().name("PAYMENT.CAPTURE.DENIED").build(),
EventType.builder().name("PAYMENT.CAPTURE.REFUNDED").build()
);
// Build webhook request
var webhookRequest = Webhook.builder()
.url("https://example.com/webhooks/paypal")
.eventTypes(eventTypes)
.build();
// Create the webhook
var webhook = client.webhooks()
.create()
.withBody(webhookRequest)
.retrieve()
.toEntity();
System.out.println("Webhook ID: " + webhook.id());
System.out.println("URL: " + webhook.url());
System.out.println("Event Types: " + webhook.eventTypes().size());
}
}
Expected Output:
List Webhooks
Retrieve all registered webhooks:
import io.github.eealba.payper.webhooks.v1.api.WebhooksApiClient;
public class ListWebhooksExample {
public static void main(String[] args) {
var client = WebhooksApiClient.create();
// List all webhooks
var webhooksList = client.webhooks()
.list()
.retrieve()
.toEntity();
System.out.println("Total Webhooks: " + webhooksList.webhooks().size());
// Print each webhook
webhooksList.webhooks().forEach(webhook -> {
System.out.println(" - ID: " + webhook.id());
System.out.println(" URL: " + webhook.url());
System.out.println(" Events: " + webhook.eventTypes().size());
});
}
}
Get Webhook Details
Retrieve details of a specific webhook:
import io.github.eealba.payper.webhooks.v1.api.WebhooksApiClient;
public class GetWebhookExample {
public static void main(String[] args) {
var client = WebhooksApiClient.create();
// Get webhook by ID
var webhook = client.webhooks()
.get()
.withId("8PT597110X687430LKGECATA")
.retrieve()
.toEntity();
System.out.println("Webhook ID: " + webhook.id());
System.out.println("URL: " + webhook.url());
// Print subscribed event types
System.out.println("Subscribed Events:");
webhook.eventTypes().forEach(eventType -> {
System.out.println(" - " + eventType.name());
System.out.println(" Description: " + eventType.description());
});
}
}
Update a Webhook
Update webhook URL or subscribed events:
import io.github.eealba.payper.webhooks.v1.api.WebhooksApiClient;
import io.github.eealba.payper.webhooks.v1.model.*;
import java.util.List;
public class UpdateWebhookExample {
public static void main(String[] args) {
var client = WebhooksApiClient.create();
// Create patch operations
var patches = List.of(
// Update URL
Patch.builder()
.op(Patch.Op.REPLACE)
.path("/url")
.value("https://example.com/webhooks/paypal-new")
.build(),
// Add new event type
Patch.builder()
.op(Patch.Op.ADD)
.path("/event_types")
.value(EventType.builder()
.name("BILLING.SUBSCRIPTION.CREATED")
.build())
.build()
);
// Update the webhook
var webhook = client.webhooks()
.update()
.withId("8PT597110X687430LKGECATA")
.withBody(new PatchRequest(patches))
.retrieve()
.toEntity();
System.out.println("Webhook updated");
System.out.println("New URL: " + webhook.url());
}
}
Delete a Webhook
Remove a webhook:
import io.github.eealba.payper.webhooks.v1.api.WebhooksApiClient;
public class DeleteWebhookExample {
public static void main(String[] args) {
var client = WebhooksApiClient.create();
// Delete webhook
client.webhooks()
.delete()
.withId("8PT597110X687430LKGECATA")
.retrieve()
.toVoid();
System.out.println("Webhook deleted successfully");
}
}
List Available Event Types
Get all available PayPal event types:
import io.github.eealba.payper.webhooks.v1.api.WebhooksApiClient;
public class ListEventTypesExample {
public static void main(String[] args) {
var client = WebhooksApiClient.create();
// List all available event types
var eventTypes = client.webhooks()
.listAllEventTypes()
.retrieve()
.toEntity();
System.out.println("Available Event Types:");
eventTypes.eventTypes().forEach(eventType -> {
System.out.println(" - " + eventType.name());
System.out.println(" " + eventType.description());
});
}
}
List Event Types for a Webhook
Get event types subscribed to by a specific webhook:
import io.github.eealba.payper.webhooks.v1.api.WebhooksApiClient;
public class ListWebhookEventTypesExample {
public static void main(String[] args) {
var client = WebhooksApiClient.create();
// List event types for specific webhook
var eventTypes = client.webhooks()
.listEventTypes()
.withId("8PT597110X687430LKGECATA")
.retrieve()
.toEntity();
System.out.println("Event Types for Webhook:");
eventTypes.eventTypes().forEach(eventType -> {
System.out.println(" - " + eventType.name());
});
}
}
Common Event Types
Here are some commonly used PayPal event types:
| Category | Event Type | Description |
|---|---|---|
| Payments | PAYMENT.CAPTURE.COMPLETED |
Payment capture completed |
PAYMENT.CAPTURE.DENIED |
Payment capture denied | |
PAYMENT.CAPTURE.REFUNDED |
Payment was refunded | |
| Orders | CHECKOUT.ORDER.COMPLETED |
Order completed |
CHECKOUT.ORDER.APPROVED |
Order approved | |
| Subscriptions | BILLING.SUBSCRIPTION.CREATED |
Subscription created |
BILLING.SUBSCRIPTION.ACTIVATED |
Subscription activated | |
BILLING.SUBSCRIPTION.CANCELLED |
Subscription cancelled | |
| Invoices | INVOICING.INVOICE.PAID |
Invoice paid |
INVOICING.INVOICE.CANCELLED |
Invoice cancelled |
Webhook Security
Verifying Webhook Signatures
PayPal signs webhook events for security. Verify signatures to ensure authenticity:
Signature Verification
Always verify webhook signatures in production to prevent unauthorized access and data tampering.
PayPal includes the following headers in webhook requests:
PAYPAL-TRANSMISSION-ID- Unique ID for the webhook eventPAYPAL-TRANSMISSION-TIME- Timestamp of the transmissionPAYPAL-TRANSMISSION-SIG- Signature for verificationPAYPAL-CERT-URL- URL to PayPal's certificatePAYPAL-AUTH-ALGO- Algorithm used for signing
Verification process (implement in your webhook endpoint):
- Retrieve the webhook event body
- Extract signature headers
- Verify signature using PayPal's certificate
- Process event only if signature is valid
Async Operations
All operations support asynchronous execution:
import io.github.eealba.payper.webhooks.v1.api.WebhooksApiClient;
import io.github.eealba.payper.webhooks.v1.model.*;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class AsyncWebhookExample {
public static void main(String[] args) {
var client = WebhooksApiClient.create();
// Create webhook asynchronously
CompletableFuture<Webhook> webhookFuture = client.webhooks()
.create()
.withBody(Webhook.builder()
.url("https://example.com/webhooks/paypal")
.eventTypes(List.of(
EventType.builder()
.name("PAYMENT.CAPTURE.COMPLETED")
.build()
))
.build())
.retrieve()
.toFuture()
.thenApply(response -> {
if (response.statusCode() == 201) {
return response.toEntity();
}
throw new RuntimeException("Failed to create webhook");
});
// Handle result
webhookFuture.thenAccept(webhook -> {
System.out.println("Webhook created: " + webhook.id());
}).exceptionally(ex -> {
System.err.println("Error: " + ex.getMessage());
return null;
});
webhookFuture.join();
}
}
Error Handling
import io.github.eealba.payper.webhooks.v1.api.WebhooksApiClient;
import io.github.eealba.payper.core.PayperException;
public class ErrorHandlingExample {
public static void main(String[] args) {
var client = WebhooksApiClient.create();
var response = client.webhooks()
.get()
.withId("INVALID_WEBHOOK_ID")
.retrieve()
.toResponse();
if (response.isSuccessful()) {
var webhook = response.toEntity();
System.out.println("Webhook: " + webhook.id());
} else {
System.err.println("API Error - Status: " + response.statusCode());
if (response.statusCode() == 404) {
System.err.println("Webhook not found");
} else {
var errorEntity = response.toErrorEntity();
System.err.println("Error: " + errorEntity.message());
}
}
}
}
Best Practices
✅ Do
- Use HTTPS URLs for webhook endpoints
- Verify webhook signatures
- Respond quickly (within 30 seconds)
- Process events asynchronously
- Implement retry logic for failed processing
- Log all webhook events
- Handle duplicate events (idempotency)
❌ Don't
- Use HTTP (non-secure) URLs
- Perform long-running operations in webhook handler
- Trust webhook data without signature verification
- Expose webhook URLs publicly
- Process events synchronously
Related Resources
- Official PayPal Webhooks API Documentation
- Webhook Events Reference - Complete list of events
- Authentication Guide - Configure credentials
- Error Handling - Advanced error handling strategies