{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-products/wallet/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["admonition"]},"type":"markdown"},"seo":{"title":"Manage webhooks","description":"User guides, API reference, and support resources.","siteUrl":"https://docs.ripple.com/products/custody","lang":"en-US","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"manage-webhooks","__idx":0},"children":["Manage webhooks"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"create-a-webhook","__idx":1},"children":["Create a webhook"]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Permissions required"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Only owners and administrators can configure webhooks."]}]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Develop a HTTPS endpoint on your server to receive webhook events"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Navigate to the ‘Settings’ page in the Wallet-as-a-Service (Palisade) console and click ‘Webhooks’"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Click ‘Create webhook’"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Enter a webhook name",{"$$mdtype":"Tag","name":"br","attributes":{},"children":[]},"This should be an identifiable name that describes the purpose of the webhook."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Optional: enter a description for the webhook"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Copy and paste the HTTPS endpoint address into the ‘URL’ section"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Select which events you want the endpoint to receive"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Click ‘Save’"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"verify-webhook-deliveries","__idx":2},"children":["Verify webhook deliveries"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["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:"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"id\": \"a6a1e8bd-30eb-419f-b6ba-e7ac11e86f84\",\n  \"name\": \"wefewfwe\",\n  \"publicKey\": \"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEpHiEkdd/ba5dU4sNCgsWrMOE6fLakHywl0OgF5aVfxkiqNh22oybRAREev7jvnwH4jqitHx79KGi6CMwiJjmaw==\",\n  // other fields omitted\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can view this public key by clicking on the webhook in the Wallet-as-a-Service (Palisade) console."]},{"$$mdtype":"Tag","name":"ol","attributes":{"start":2},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Extract the signature from the webhook event headers in the URL (it will be in ASN.1 DER format, base64-encoded)"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Create a SHA-256 hash of the base64-encoded payload"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Use the public key to verify that the signature matches the payload hash"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Most programming languages have cryptography libraries that support ECDSA verification."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"code-examples","__idx":3},"children":["Code Examples"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"python","__idx":4},"children":["Python"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"python","header":{"controls":{"copy":{}}},"source":"import hashlib\nimport base64\nfrom cryptography.hazmat.primitives import hashes\nfrom cryptography.hazmat.primitives.asymmetric import ec\nfrom cryptography.hazmat.primitives.serialization import load_der_public_key\n\ndef verify_webhook(public_key_b64: str, signature_b64: str, payload_b64: str) -> bool:\n    \"\"\"\n    Verify a Palisade webhook signature.\n\n    Args:\n        public_key_b64: Base64-encoded public key from webhook creation\n        signature_b64: Base64-encoded signature from the 'Signature' header\n        payload_b64: The base64-encoded payload string from the webhook body\n\n    Returns:\n        True if signature is valid, False otherwise\n    \"\"\"\n    public_key = load_der_public_key(base64.b64decode(public_key_b64))\n    signature = base64.b64decode(signature_b64)\n    payload_hash = hashlib.sha256(payload_b64.encode()).digest()\n\n    try:\n        public_key.verify(signature, payload_hash, ec.ECDSA(hashes.SHA256()))\n        return True\n    except Exception:\n        return False\n","lang":"python"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"javascript-nodejs","__idx":5},"children":["JavaScript (Node.js)"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"javascript","header":{"controls":{"copy":{}}},"source":"const crypto = require('crypto');\n\n/**\n * Verify a Palisade webhook signature.\n *\n * @param {string} publicKeyB64 - Base64-encoded public key from webhook creation\n * @param {string} signatureB64 - Base64-encoded signature from the 'Signature' header\n * @param {string} payloadB64 - The base64-encoded payload string from the webhook body\n * @returns {boolean} - True if signature is valid\n */\nfunction verifyWebhook(publicKeyB64, signatureB64, payloadB64) {\n  const publicKey = crypto.createPublicKey({\n    key: Buffer.from(publicKeyB64, 'base64'),\n    format: 'der',\n    type: 'spki'\n  });\n\n  const payloadHash = crypto.createHash('sha256').update(payloadB64).digest();\n\n  return crypto.verify(\n    null,\n    payloadHash,\n    publicKey,\n    Buffer.from(signatureB64, 'base64')\n  );\n}\n","lang":"javascript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"go","__idx":6},"children":["Go"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"go","header":{"controls":{"copy":{}}},"source":"package main\n\nimport (\n\t\"crypto/ecdsa\"\n\t\"crypto/sha256\"\n\t\"crypto/x509\"\n\t\"encoding/base64\"\n)\n\n// VerifyWebhook verifies a Palisade webhook signature.\nfunc VerifyWebhook(publicKeyB64, signatureB64, payloadB64 string) (bool, error) {\n\tpublicKeyDER, err := base64.StdEncoding.DecodeString(publicKeyB64)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tpubKey, err := x509.ParsePKIXPublicKey(publicKeyDER)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\tecdsaPubKey, ok := pubKey.(*ecdsa.PublicKey)\n\tif !ok {\n\t\treturn false, err\n\t}\n\n\tsignature, err := base64.StdEncoding.DecodeString(signatureB64)\n\tif err != nil {\n\t\treturn false, err\n\t}\n\n\thash := sha256.Sum256([]byte(payloadB64))\n\n\treturn ecdsa.VerifyASN1(ecdsaPubKey, hash[:], signature), nil\n}\n","lang":"go"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"security-requirements--best-practices","__idx":7},"children":["Security Requirements & Best Practices"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["HTTPS Only"]},": All webhook endpoints must use HTTPS for secure communication"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Signature Verification"]},": Always verify the webhook signature to ensure authenticity"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Response Codes"]},": Return a 200 OK response code to acknowledge receipt of the webhook"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"webhook-settings","__idx":8},"children":["Webhook settings"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The console lists your webhooks in a table after you create them."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can view or delete webhooks by clicking the three dots in the ‘actions’ column of the table."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When you view a webhook, you see the following information:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Name"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Description"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["URL"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Public key"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Subscriptions: the event subscriptions configured"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Who created the webhook and when"]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"API documentation"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["See our ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/products/wallet/api-docs/palisade-api/palisade-api"},"children":["Wallet-as-a-Service (Palisade) API reference"]}," for information on how to configure webhooks via the API."]}]}]},"headings":[{"value":"Manage webhooks","id":"manage-webhooks","depth":1},{"value":"Create a webhook","id":"create-a-webhook","depth":2},{"value":"Verify webhook deliveries","id":"verify-webhook-deliveries","depth":2},{"value":"Code Examples","id":"code-examples","depth":3},{"value":"Python","id":"python","depth":4},{"value":"JavaScript (Node.js)","id":"javascript-nodejs","depth":4},{"value":"Go","id":"go","depth":4},{"value":"Security Requirements & Best Practices","id":"security-requirements--best-practices","depth":2},{"value":"Webhook settings","id":"webhook-settings","depth":2}],"frontmatter":{"title":"Manage webhooks","seo":{"title":"Manage webhooks"}},"lastModified":"2026-02-27T16:34:32.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/products/wallet/user-interface/integrations/manage-webhooks","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}