π‘ How WebHooks β Subscribers via Clara API
This guide describes how to manage webhook subscribers using Claraβs /api/v1/subscribers
endpoint, and explains the internal execution and consumption logic via WebhookConsumerService
.
π Authentication Requirements
- Use mutual TLS (MTLS) for secure two-way certificate validation.
- Obtain an OAuth2 access token via
/oauth/token
. - Use the token in the
Authorization: Bearer
header for all API requests.
π Endpoints
π₯ Retrieve Subscribers
GET /api/v1/subscribers
Query Parameters:
Name | Type | Description |
---|---|---|
page | integer | Page index (0-based) |
size | integer | Number of results per page |
uuid | uuid | Filter by subscriber UUID |
name | string | Name of the subscriber |
callbackUrl | string | Callback URL |
enabled | boolean | Whether the subscriber is active |
events | string | Comma-separated list of subscribed events |
companyUuid | uuid | Optional UUID of the company |
β Create a Subscriber
POST /api/v1/subscribers
Body Example:
{
"name": "Accounting Service",
"callbackUrl": "https://example.com/webhook",
"events": ["PAYMENT_PAID", "CARD_CREATION_REQUEST_CREATED"],
"enabled": true,
"companyUuid": "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed"
}
π Update a Subscriber
PATCH /api/v1/subscribers/{uuid}
ποΈ Delete a Subscriber
DELETE /api/v1/subscribers/{uuid}
π§ Manage Events on a Subscriber
POST /api/v1/subscribers/add-event
DELETE /api/v1/subscribers/delete-event
βοΈ Webhook Execution & Processing Flow
The WebHook event lifecycle consists of two key services working together:
π¬ WebhookConsumerService
(Kafka Listener & Subscriber Notifier)
WebhookConsumerService
(Kafka Listener & Subscriber Notifier)This service listens to the Kafka topic and delivers the webhook to external subscribers. It ensures reliable delivery and avoids duplicate processing. It uses WebhookService:
@KafkaListener(topics = "${clara.kafka.webhook.topic.create.request}",
containerFactory = "kafkaListenerContainerFactory")
public void consumeWebhookRequest(ConsumerRecord<String, byte[]> input) {
var webhookRequest = SerdesUtils.deserialize(avroDeserializer, input);
if (Objects.nonNull(webhookRequest)) {
webhookRequestEntityRepository.findById(webhookRequest.getId())
.ifPresentOrElse(webhookRequestEntity -> {}, () -> {
log.debug("Processing webhook with id: {}", webhookRequest.getId());
webhookService.saveAndSendWebHook(webhookRequest);
});
}
}
β
WebhookService
WebhookService
This service delivers Webhooks to external subscribers via a POST
call
webhookService.sendWebHook(
webhookRequest.getCompanyUuid(),
webhookRequest.getId(),
webhookRequest.getEvent(),
webhookRequest.getMetadata(),
webhookRequest.getErrorCode(),
webhookRequest.getErrorMessage()
);
Together, these services ensure webhook events are decoupled, auditable, and reliably delivered.
πΌοΈ WebHook Architecture Overview
Flow Overview:
- An event is triggered by a source system (e.g., Payments, Cards).
WebhookConsumerService
subscribes to the topic and consumes the event. It usesWebhookService
- The
WebhookService
service sends aPOST
request to the configured Subscriber Endpoint.
Flow Diagram:
[Event Source]
β
βΌ
[WebhookConsumerService]
β
βΌ
[Kafka Topic]
β
βΌ
[WebhookService]
β
βΌ
[Subscriber Endpoint]
π Summary
- Use
/api/v1/subscribers
to manage your webhook callback endpoints. - Each subscriber can listen to one or more Clara platform events.
- Events are dispatched by
WebhookService
(implemented in your API) and delivered byWebhookConsumerService
. - Clara uses secure, resilient, and decoupled architecture to ensure webhook reliability.
π Sending WebHook Events from an API
You can also send WebHook events directly from your service logic or API controller using another WebhookService
implemented in your API.
Here's an example using the WebhookRequest
builder:
var webhookRequest = WebhookRequest.newBuilder()
.setId(cardResponse.getId())
.setCompanyUuid(UUID.fromString(cardResponse.getData().getCard().getCompanyUuid()))
.setEvent(CARD_CREATION_REQUEST_ERROR.name())
.setTimestamp(LocalDateTime.now())
.setErrorCode(cardResponse.getData().getCard().getErrorCode())
.setErrorMessage(cardResponse.getData().getCard().getErrorMessage())
.build();
webhookService.send(webhookRequest);
This sends a structured webhook event using the built WebhookRequest
. Ensure WebhookService.send(...)
is appropriately configured to publish to Kafka or forward via HTTP as needed.
WebhookRequest
. Ensure WebhookService.send(...)
is appropriately configured to publish to Kafka or forward via HTTP as needed.π§© WebhookService β Implementation Example
Here's how the WebhookService
class is implemented to send events using Kafka:
@Slf4j
@Service
public class WebhookService {
private final KafkaTemplate<String, byte[]> kafkaTemplate;
private final String requestTopic;
private static final AvroSerializer<WebhookRequest> webhookRequestAvroSerializer =
AvroSerializer.of(WebhookRequest.SCHEMA$);
public WebhookService(KafkaTemplate<String, byte[]> kafkaTemplate,
@Value("${clara.data-writer.kafka.webhook.topic.create.request}") String requestTopic) {
this.kafkaTemplate = kafkaTemplate;
this.requestTopic = requestTopic;
}
public void send(WebhookRequest webhookRequest) {
KafkaUtils.serializeAndSendNonReactive(
webhookRequestAvroSerializer,
webhookRequest,
webhookRequest.getId(),
requestTopic,
kafkaTemplate
);
}
}
This service serializes a WebhookRequest
object using Avro and sends it to a Kafka topic defined in the application configuration.