Webhooks - Java

I translated the Python Webhook code on the site into Java and my code is below. Any thoughts on why this isn’t pulling values from Fireblocks? Is my public key correct? I am using the https://api.fireblocks.io/v1 instance:

import com.bakkt.custody.provider.model.Event;
import com.bakkt.custody.provider.model.ExternalWalletAssetRemoved;
import com.bakkt.custody.provider.model.TransactionCreated;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.*;
import io.micronaut.http.annotation.Consumes;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Post;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WebhookController {

  private static final Logger LOG = LoggerFactory.getLogger(WebhookController.class);
  private PublicKey fireblocksPublicKey;
  private final ObjectMapper objectMapper;

  public WebhookController(ObjectMapper objectMapper) throws Exception {
    this.objectMapper = objectMapper;

    String fireblocksPublicKeyStr =
    -----BEGIN PUBLIC KEY-----
    -----END PUBLIC KEY-----
            .replace("-----BEGIN PUBLIC KEY-----\n", "")
            .replace("-----END PUBLIC KEY-----\n", "")
            .replace("\n", "");

    byte[] encoded = Base64.getDecoder().decode(fireblocksPublicKeyStr);
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded);
    KeyFactory kf = KeyFactory.getInstance("RSA");
    this.fireblocksPublicKey = kf.generatePublic(keySpec);

  public HttpResponse<String> handleWebhook(
      HttpRequest<String> request, @Header("Fireblocks-Signature") String fireblocksSignature)
      throws JsonProcessingException {
    String body = request.getBody().orElse("");
    LOG.info("Incoming request body: {}", body);

    try {
      boolean isSignatureValid =
          verifySignature(body.getBytes(StandardCharsets.UTF_8), fireblocksSignature);
      if (!isSignatureValid) {
        return HttpResponse.unauthorized();

      LOG.info("Received request with body: {} and signature: {}", body, fireblocksSignature);

      Event event = objectMapper.readValue(body, Event.class);

      if (event instanceof ExternalWalletAssetRemoved) {
        ExternalWalletAssetRemoved externalWalletAssetRemovedEvent =
            (ExternalWalletAssetRemoved) event;
            "Received External Wallet Asset Removed event: {}", externalWalletAssetRemovedEvent);
      } else if (event instanceof TransactionCreated) {
        TransactionCreated transactionCreatedEvent = (TransactionCreated) event;
        LOG.info("Received Transaction Created event: {}", transactionCreatedEvent);
      } else {
        LOG.warn("Received unknown event: {}", event);

      return HttpResponse.ok("Event received");
    } catch (Exception e) {
      LOG.error("Error handling webhook", e);
      return HttpResponse.serverError("Error handling webhook");

  private boolean verifySignature(byte[] data, String signature) throws Exception {
    Signature sig = Signature.getInstance("SHA512withRSA");
    LOG.info("Verifying signature...");
    boolean isVerified = sig.verify(Base64.getUrlDecoder().decode(signature));
    LOG.info("Signature verification result: {}", isVerified);
    return isVerified;

Hi @moza,

My name is Alon and I am part of the Solutions Engineering team at Fireblocks.

The public key you’re using seems fine and matches the expected public key for the non-sandbox webhooks - here

Do you not get a request at all? meaning the LOG.info command in your handleWebhook method is not called?

Try to do the following:

  1. You must configure your own webhook URL (that is your own domain, not the https://api.fireblocks.io/v1 URL), to do this follow this guide
  2. Sandbox environments need a different public key (as mentioned above) - make sure to use that one in the event you’re using a Sandbox environment
  3. Webhooks are automatically sent as a response to events in your workspace, if nothing happens on your workspace then you won’t get webhooks. Try to make a transfer or transfer some assets into the workspace, you should get the webhook as a response
  4. Depending on your environment, it might be that some firewall or other network component is dropping the request from being received, check all network components from your webhook server (which needs to have access to the internet directly) to the internet and make sure none of them are dropping the traffic

Please let me know if the issue persists.