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.