Skip to main content

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:

  1. A webhook endpoint — An HTTP endpoint that accepts POST requests with the event payload
  2. 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.

WebhookEndpoint.java
@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();
}
}
warning

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 StatusIntegration Hub Behavior
200-299Delivery successful — Integration Hub acknowledges the event message
300-599Delivery failed — Integration Hub retries, then routes to dead-letter topic
TimeoutIntegration 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.

Create event type definition
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:

FieldDescriptionExample
idUUID identifier for the event definition"11111111-1111-1111-1111-111111111111"
sourceServiceThe upstream service producing this event"keycloak"
eventTypeEvent type name"user.created"
resourceTypeThe resource category affected"user"
operationTypeThe 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:

Register subscription with Basic auth
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:

AUTH_TYPE_BASIC
{
"type": "AUTH_TYPE_BASIC",
"basic": {
"username": "<YOUR_USERNAME>",
"password": "<YOUR_PASSWORD>"
}
}

Sets Authorization: Basic <base64(username:password)> header.

OAuth2:

AUTH_TYPE_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):

AUTH_TYPE_JWT
{
"type": "AUTH_TYPE_JWT",
"jwt": {
"token": "<YOUR_BEARER_TOKEN>"
}
}

Sets Authorization: Bearer <token> header with the pre-shared token.

API Key:

AUTH_TYPE_APIKEY
{
"type": "AUTH_TYPE_APIKEY",
"apikey": {
"key": "<YOUR_API_KEY>",
"headerName": "X-API-KEY"
}
}

Sets a custom header with the API key value.

tip

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.

Idempotency check
public class EventDeduplicator {

private final Set<String> processedEvents = ConcurrentHashMap.newKeySet();

public boolean isAlreadyProcessed(String eventId) {
return !processedEvents.add(eventId);
}
}
note

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:

List subscriptions for your event
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​

  1. The Integration Hub resolves your subscription for the user creation event
  2. Integration Hub creates a delivery envelope with your endpoint and Basic auth credentials
  3. The Integration Hub sends an HTTP POST to https://my-service.example.com/webhooks/events
  4. Your endpoint responds with 200 OK
  5. 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's sourceService, eventType, resourceType, and operationType match the producer's event fields.
  • 401 Unauthorized in dead-letter topic — Authentication credentials in the subscription are incorrect. Update the subscription with valid credentials.
  • 504 Gateway Timeout in dead-letter topic — Your endpoint exceeds the delivery timeout. Respond immediately with 2xx and process asynchronously.
  • Duplicate events received — This is expected behavior with at-least-once delivery. Implement idempotent processing using the event ID.
  • 503 Service Unavailable in 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.