> ## Documentation Index
> Fetch the complete documentation index at: https://developers.clara.team/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Subscribe to transaction events via webhooks.

<Warning>This service is not yet available in v3. Available in **v1** only.</Warning>

# 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:

```json theme={null}
{
  "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)

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:

```java theme={null}
@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`

This service delivers Webhooks to external subscribers via a `POST` call

```java theme={null}
webhookService.sendWebHook(
    webhookRequest.getCompanyUuid(),
    webhookRequest.getId(),
    webhookRequest.getEvent(),
    webhookRequest.getMetadata(),
    webhookRequest.getErrorCode(),
    webhookRequest.getErrorMessage()
);
```

<br />

Together, these services ensure webhook events are decoupled, auditable, and reliably delivered.

## WebHook Architecture Overview

**Flow Overview:**

1. An **event** is triggered by a source system (e.g., Payments, Cards).
2. `WebhookConsumerService` subscribes to the topic and consumes the event. It uses `WebhookService`
3. The `WebhookService` service sends a `POST` 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 by `WebhookConsumerService`.
* 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:

```java theme={null}
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.

## WebhookService – Implementation Example

Here's how the `WebhookService` class is implemented to send events using Kafka:

```java theme={null}
@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.
