Building Consumers
Goal
Build a subscriber service that receives platform events from Integration Hub via HTTP webhooks. Register a subscription to specific event types and configure authentication for secure delivery.
Audience
Developers building services that need to react to platform events — such as user lifecycle changes, policy updates, access events, or organization membership changes.
Prerequisites
- Access to the Subscription Management service
- An HTTP endpoint accessible from the Integration Hub
- Understanding of the event types your service needs to receive
- Authentication credentials for your webhook endpoint
Before You Start
Integration Hub delivers events to subscriber endpoints via HTTP webhooks. The delivery flow works as follows:
Your service needs two things:
- A webhook endpoint — An HTTP endpoint that accepts POST requests with the event payload
- A subscription registration — A subscription record in the Subscription Management service that maps your endpoint to specific event types
Worked Example
In this guide, you build a webhook endpoint that receives user lifecycle events, register a subscription with Basic authentication, and handle incoming deliveries.
Steps
1. Build the webhook endpoint
Create an HTTP endpoint that accepts POST requests. The Integration Hub sends the event payload as the request body with the configured authentication.
@Path("/webhooks/events")
public class WebhookEndpoint {
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response handleEvent(JsonObject payload) {
String eventId = payload.getString("eventId");
// Idempotency check — skip if already processed
if (isAlreadyProcessed(eventId)) {
return Response.ok().build();
}
// Process the event asynchronously
processEventAsync(payload);
// Respond immediately with 2xx
return Response.ok().build();
}
}
The Integration Hub has a short delivery timeout. Your endpoint must respond within this window, or the system treats the delivery as failed and routes it to the dead-letter topic. Respond with 2xx immediately and process the event asynchronously.
Response requirements:
| HTTP Status | Integration Hub Behavior |
|---|---|
200-299 | Delivery successful — Integration Hub acknowledges the event message |
300-599 | Delivery failed — Integration Hub retries, then routes to dead-letter topic |
| Timeout | Integration Hub treats as failure and routes to dead-letter topic |
2. Register the event type
Before creating a subscription, ensure the event type you want to receive exists in the Subscription Management service. Use the REST API to check and create it if needed.
curl -X POST https://<SUBSCRIPTION_SERVICE_HOST>/api/v1/events \
-H "Content-Type: application/json" \
-d '{
"event": {
"id": "11111111-1111-1111-1111-111111111111",
"sourceService": "keycloak",
"eventType": "user.created",
"resourceType": "user",
"operationType": "CREATE"
}
}'
Event definition fields:
| Field | Description | Example |
|---|---|---|
id | UUID identifier for the event definition | "11111111-1111-1111-1111-111111111111" |
sourceService | The upstream service producing this event | "keycloak" |
eventType | Event type name | "user.created" |
resourceType | The resource category affected | "user" |
operationType | The operation performed (CREATE, UPDATE, DELETE) | "CREATE" |
3. Register your subscription
Create a subscription that maps the event type to your webhook endpoint with the appropriate authentication:
curl -X POST https://<SUBSCRIPTION_SERVICE_HOST>/api/v1/subscriptions \
-H "Content-Type: application/json" \
-d '{
"subscription": {
"eventId": "11111111-1111-1111-1111-111111111111",
"subscriberService": "my-service",
"deliveryEndpoint": "https://my-service.example.com/webhooks/events",
"callbackProtocol": "CALLBACK_PROTOCOL_HTTP",
"requestMethod": "REQUEST_POST",
"active": true,
"payloadType": "PAYLOAD_TYPE_JSON",
"auth": {
"type": "AUTH_TYPE_BASIC",
"basic": {
"username": "<YOUR_WEBHOOK_USERNAME>",
"password": "<YOUR_WEBHOOK_PASSWORD>"
}
}
}
}'
4. Choose the authentication type
Integration Hub supports four authentication types for webhook delivery. Choose the one that matches your endpoint's security model:
Basic Authentication:
{
"type": "AUTH_TYPE_BASIC",
"basic": {
"username": "<YOUR_USERNAME>",
"password": "<YOUR_PASSWORD>"
}
}
Sets Authorization: Basic <base64(username:password)> header.
OAuth2:
{
"type": "AUTH_TYPE_OAUTH2",
"oauth2": {
"clientId": "<YOUR_CLIENT_ID>",
"clientSecret": "<YOUR_CLIENT_SECRET>",
"tokenUrl": "https://auth.example.com/oauth/token",
"scope": "read write"
}
}
Performs token exchange before each delivery, then sets Authorization: Bearer <token>.
JWT (Bearer Token):
{
"type": "AUTH_TYPE_JWT",
"jwt": {
"token": "<YOUR_BEARER_TOKEN>"
}
}
Sets Authorization: Bearer <token> header with the pre-shared token.
API Key:
{
"type": "AUTH_TYPE_APIKEY",
"apikey": {
"key": "<YOUR_API_KEY>",
"headerName": "X-API-KEY"
}
}
Sets a custom header with the API key value.
For service-to-service communication, use OAuth2 with client credentials. For simpler setups, API Key provides a straightforward authentication mechanism with a custom header name.
5. Implement idempotent processing
Integration Hub provides at-least-once delivery. The same event may be delivered more than once if a delivery acknowledgment fails. Implement idempotent processing using the event ID as a deduplication key.
public class EventDeduplicator {
private final Set<String> processedEvents = ConcurrentHashMap.newKeySet();
public boolean isAlreadyProcessed(String eventId) {
return !processedEvents.add(eventId);
}
}
For production environments, use a persistent deduplication store (e.g., a database table or distributed cache) instead of an in-memory set. In-memory sets are lost on restart.
6. Verify your subscription
Confirm your subscription is active by querying the Subscription Management service:
curl https://<SUBSCRIPTION_SERVICE_HOST>/api/v1/subscriptions/event/11111111-1111-1111-1111-111111111111
The response includes all subscriptions registered for the specified event ID, with their delivery endpoint, authentication type, and active status.
Validation Scenario
Scenario
A user creation event is published to Integration Hub, and your subscriber endpoint receives it via HTTP webhook with Basic authentication.
Expected Result
- The Integration Hub resolves your subscription for the user creation event
- Integration Hub creates a delivery envelope with your endpoint and Basic auth credentials
- The Integration Hub sends an HTTP POST to
https://my-service.example.com/webhooks/events - Your endpoint responds with
200 OK - The event bus acknowledges the delivery
How to Verify
- API evidence: Query the subscriptions API to verify your subscription shows as
active: true - Logs: Integration Hub logs show delivery attempt and result for your endpoint
- Audit evidence: Audit service records a successful delivery audit entry
- DLT evidence: If delivery failed, query the dead-letter topic API to see the failed event with error details
Troubleshooting
- Webhook not receiving events — Verify subscription is
active: true. Check that the event definition'ssourceService,eventType,resourceType, andoperationTypematch the producer's event fields. 401 Unauthorizedin dead-letter topic — Authentication credentials in the subscription are incorrect. Update the subscription with valid credentials.504 Gateway Timeoutin dead-letter topic — Your endpoint exceeds the delivery timeout. Respond immediately with2xxand process asynchronously.- Duplicate events received — This is expected behavior with at-least-once delivery. Implement idempotent processing using the event ID.
503 Service Unavailablein dead-letter topic — Your endpoint is down or unreachable from the Integration Hub. Verify network connectivity and endpoint health.
Next Steps
To manage subscriptions programmatically (create, update, delete via gRPC or REST), see Using Integration Hub gRPC APIs.