Skip to content

Manage webhooks

Create a webhook

Permissions required

Only owners and administrators can configure webhooks.

  1. Develop a HTTPS endpoint on your server to receive webhook events
  2. Navigate to the ‘Settings’ page in the Wallet-as-a-Service (Palisade) console and click ‘Webhooks’
  3. Click ‘Create webhook’
  4. Enter a webhook name
    This should be an identifiable name that describes the purpose of the webhook.
  5. Optional: enter a description for the webhook
  6. Copy and paste the HTTPS endpoint address into the ‘URL’ section
  7. Select which events you want the endpoint to receive
  8. Click ‘Save’

Verify webhook deliveries

  1. After you create a webhook, Wallet-as-a-Service (Palisade) generates and returns a P-256 ECDSA public key in ASN.1 DER format. For example:
{
  "id": "a6a1e8bd-30eb-419f-b6ba-e7ac11e86f84",
  "name": "wefewfwe",
  "publicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpHiEkdd/ba5dU4sNCgsWrMOE6fLakHywl0OgF5aVfxkiqNh22oybRAREev7jvnwH4jqitHx79KGi6CMwiJjmaw==",
  // other fields omitted
}

You can view this public key by clicking on the webhook in the Wallet-as-a-Service (Palisade) console.

  1. Extract the signature from the webhook event headers in the URL (it will be in ASN.1 DER format, base64-encoded)
  2. Create a SHA-256 hash of the base64-encoded payload
  3. Use the public key to verify that the signature matches the payload hash

Most programming languages have cryptography libraries that support ECDSA verification.

Code Examples

Python

import hashlib
import base64
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.serialization import load_der_public_key

def verify_webhook(public_key_b64: str, signature_b64: str, payload_b64: str) -> bool:
    """
    Verify a Palisade webhook signature.

    Args:
        public_key_b64: Base64-encoded public key from webhook creation
        signature_b64: Base64-encoded signature from the 'Signature' header
        payload_b64: The base64-encoded payload string from the webhook body

    Returns:
        True if signature is valid, False otherwise
    """
    public_key = load_der_public_key(base64.b64decode(public_key_b64))
    signature = base64.b64decode(signature_b64)
    payload_hash = hashlib.sha256(payload_b64.encode()).digest()

    try:
        public_key.verify(signature, payload_hash, ec.ECDSA(hashes.SHA256()))
        return True
    except Exception:
        return False

JavaScript (Node.js)

const crypto = require('crypto');

/**
 * Verify a Palisade webhook signature.
 *
 * @param {string} publicKeyB64 - Base64-encoded public key from webhook creation
 * @param {string} signatureB64 - Base64-encoded signature from the 'Signature' header
 * @param {string} payloadB64 - The base64-encoded payload string from the webhook body
 * @returns {boolean} - True if signature is valid
 */
function verifyWebhook(publicKeyB64, signatureB64, payloadB64) {
  const publicKey = crypto.createPublicKey({
    key: Buffer.from(publicKeyB64, 'base64'),
    format: 'der',
    type: 'spki'
  });

  const payloadHash = crypto.createHash('sha256').update(payloadB64).digest();

  return crypto.verify(
    null,
    payloadHash,
    publicKey,
    Buffer.from(signatureB64, 'base64')
  );
}

Go

package main

import (
	"crypto/ecdsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/base64"
)

// VerifyWebhook verifies a Palisade webhook signature.
func VerifyWebhook(publicKeyB64, signatureB64, payloadB64 string) (bool, error) {
	publicKeyDER, err := base64.StdEncoding.DecodeString(publicKeyB64)
	if err != nil {
		return false, err
	}

	pubKey, err := x509.ParsePKIXPublicKey(publicKeyDER)
	if err != nil {
		return false, err
	}

	ecdsaPubKey, ok := pubKey.(*ecdsa.PublicKey)
	if !ok {
		return false, err
	}

	signature, err := base64.StdEncoding.DecodeString(signatureB64)
	if err != nil {
		return false, err
	}

	hash := sha256.Sum256([]byte(payloadB64))

	return ecdsa.VerifyASN1(ecdsaPubKey, hash[:], signature), nil
}

Security Requirements & Best Practices

  • HTTPS Only: All webhook endpoints must use HTTPS for secure communication
  • Signature Verification: Always verify the webhook signature to ensure authenticity
  • Response Codes: Return a 200 OK response code to acknowledge receipt of the webhook

Webhook settings

The console lists your webhooks in a table after you create them.

You can view or delete webhooks by clicking the three dots in the ‘actions’ column of the table.

When you view a webhook, you see the following information:

  • Name
  • Description
  • URL
  • Public key
  • Subscriptions: the event subscriptions configured
  • Who created the webhook and when
API documentation

See our Wallet-as-a-Service (Palisade) API reference for information on how to configure webhooks via the API.