# Webhooks overview ## What are webhooks? Wallet-as-a-Service (Palisade) sends automated messages called webhooks to your back-end systems whenever specific events occur on the platform. The system sends the message, or payload, to a unique URL on your server that you designate to receive webhook events. ## Why are webhooks beneficial? The automated nature of webhooks allows organizations to receive guaranteed, real-time updates about any interactions with their wallets (including creation of new wallets, deposits and withdrawals). This push-based approach eliminates the need for API/UI polling and ensures customers are immediately notified of important updates. ## Webhook payload format Wallet-as-a-Service (Palisade) delivers webhook messages as POST requests containing JSON objects with a base64-encoded payload. For example: ```json { "domain": "WALLET", "timestamp": "2025-05-08T14:15:37Z", "payload": "eyJpZCI6IjAxOTYxNTNiLTY3YmMtN2NkMy1iNTExLTM1NDM3M2QyODEzMCIsICJ2YXVsdElkIjoiMDE5NjE1MmQtNTI5NC03MzlkLTk5NDUtMmE0OTlmOWUzOTg5IiwgIm9yZ2FuaXphdGlvbklkIjoiMjFjODEzMTktNWI4My00NWY5LWI2NDgtNDIwNTUwODRhZjE1IiwgInF1b3J1bUlkIjoiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAwIiwgImNyZWF0ZWRCeSI6ImE1NWRmOWUwLWUxNGEtNDQxMC1hOTgzLTEyYWZhZTQ2NjYyZiIsICJjcmVhdGVkQXQiOiIyMDI1LTA0LTA4VDExOjQ4OjU2Ljg5OTA4NloiLCAidXBkYXRlZEF0IjoiMjAyNS0wNC0wOFQxMTo0ODo1Ni45MDA0OTBaIiwgIm5hbWUiOiJld3FmZXciLCAiZGVzY3JpcHRpb24iOiIiLCAiYWRkcmVzcyI6IjB4NDY0NDMyMGYzMUQ2OTU4RWQ4NjAzRWI2NjYwNDQ5NTBBYTY5NzAyZSIsICJwdWJsaWNLZXkiOiIwNDgxY2IwMmU4MjFlNTVhMmM2MTk2ZmZkZTM4MGJhM2I0OTgxN2JkYmYwMmYzMTVkYzI4YjU2ZjcwNzkyZDU2ZTZhZGFjOTE3ZTdhZGFmODdmMTBjMDg4NDA4YThjNmEwZTZkMTgwNzkzYzA1MGMzZDBjODc3MWNiOWRkZjgyNThkIiwgImtleXN0b3JlIjoiSFNNIiwgImJsb2NrY2hhaW4iOiJBUkJJVFJVTSIsICJzZXR0aW5ncyI6e30sICJzdGF0dXMiOiJQUk9WSVNJT05FRCJ9", } ``` When decoded, the payload contains detailed information about the blockchain event. For example: ```json { "id": "0196153b-67bc-7cd3-b511-354373d28130", "vaultId": "0196152d-5294-739d-9945-2a499f9e3989", "organizationId": "21c81319-5b83-45f9-b648-42055084af15", "createdBy": "a55df9e0-e14a-4410-a983-12afae46662f", "createdAt": "2025-04-08T11:48:56.899086Z", "updatedAt": "2025-04-08T11:48:56.900490Z", "name": "My Wallet", "address": "0x4644320f31D6958Ed8603Eb666044950Aa69702e", "publicKey": "0481cb02e821e55a2c6196ffde380ba3b49817bdbf02f315dc28b56f70792d56e6adac917e7adaf87f10c088408a8c6a0e6d180793c050c3d0c8771cb9ddf8258d", "keystore": "HSM", "blockchain": "ARBITRUM", "settings": {}, "status": "PROVISIONED" } ``` The webhook contains a `signature` header you can use to verify that the payload is authentic. For example: `MEQCIGjBwNKzzfqK9/Rb3Q2OQCyCuUiOOQz7vZwQ9iqInz76AiB/bvRn5iNUAkeVT80/pwhQ2LUajE6Mb2JtGt2mRmJMpg==` ## Retry Behaviour Your server must return an HTTP-200 (OK) response to confirm successful receipt of a webhook notification. If your server does not respond, Wallet-as-a-Service (Palisade) automatically retries the request several times based on the following schedule (in seconds): 0, 60, 120, 180, 320, 480, 840, 1500, 2820, 5400. The system does not retry for client-side errors (HTTP 4xx) except for the following cases: 429 - Too Many Requests: Indicates rate limits have been exceeded. 408 - Request Timeout: Indicates the server took too long to respond. After 10 failed attempts, the system marks the notification as failed and stops retrying. ## Event Ordering Wallet-as-a-Service (Palisade) strives to send notifications in order (per resource), but we cannot guarantee delivery sequence. Design your endpoint to process events independently without relying on their delivery order. ## Subscription Domains When you create a webhook, you subscribe to one or more domains. Each domain sends notifications when the corresponding resource changes state. | Domain | Description | Payload | | --- | --- | --- | | **TRANSACTION** | Transaction status changes (transfers, deposits, withdrawals) | [Transaction object](https://docs.ripple.com/products/wallet/api-docs/palisade-api/palisade-api/transactions/transactionsservice_gettransaction#transactions/transactionsservice_gettransaction/response&c=200/body) | | **WALLET** | Wallet status changes (creation, provisioning) | [Wallet object](https://docs.ripple.com/products/wallet/api-docs/palisade-api/palisade-api/wallets/vaultservice_getwallet#wallets/vaultservice_getwallet/response&c=200/body) | | **APPROVAL** | Approval request updates | [Approval object](https://docs.ripple.com/products/wallet/api-docs/palisade-api/palisade-api/approvals/approvalservice_getapprovalsummary#approvals/approvalservice_getapprovalsummary/t=response&c=200&path=approval) | ### Transaction Domain You receive a webhook notification whenever a transaction transitions to a new status. The payload contains the full transaction object with its current state. | Status | Description | Terminal? | | --- | --- | --- | | `REQUESTED` | Transaction created | No | | `POLICY_CHECK_PENDING` | Validating against policies | No | | `POLICY_CHECK_PASSED` | Policy checks passed | No | | `APPROVAL_CHECK_PENDING` | Waiting for approvals | No | | `APPROVAL_CHECK_PASSED` | Approvals complete | No | | `COMPILATION_PENDING` | Preparing for blockchain | No | | `COMPILED` | Ready for signing | No | | `SIGNATURE_PENDING` | Waiting for signature | No | | `SIGNED` | Signed successfully | No | | `PUBLISH_PENDING` | Submitting to network | No | | `PUBLISHED` | Submitted to blockchain | No | | `CONFIRMATION_PENDING` | Awaiting block confirmation | No | | `CONFIRMED` | Confirmed on blockchain | ✅ Yes | | `REJECTED` | Rejected by policy or approval | ✅ Yes | | `FAILED` | Technical failure | ✅ Yes | For more details on transaction status flow, see [Transactions overview](/products/wallet/user-interface/transactions/overview). #### Transaction Payload Example ```json { "domain": "TRANSACTION", "timestamp": "2025-05-08T14:30:00Z", "payload": "base64-encoded-transaction-object" } ``` When decoded, the payload contains the transaction object. Key fields include: ```json { "id": "019c94f1-cc8c-79b4-9c0f-bc7edaabc267", "vaultId": "0196152d-5294-739d-9945-2a499f9e3989", "walletId": "0196153b-67bc-7cd3-b511-354373d28130", "organizationId": "21c81319-5b83-45f9-b648-42055084af15", "status": "CONFIRMED", "blockchain": "ETHEREUM", "hash": "0x8a4c5e9f2b1d7c3a6e8f0b2d4c6a8e0f2b4d6c8a0e2f4b6d8c0a2e4f6b8d0c2e", "destination": { "address": "0x742d35Cc6634C0532925a3b844Bc9e7595f2E8Ba" }, "asset": { "symbol": "ETH" }, "qty": "1.500000000000000000", "createdAt": "2025-05-08T14:25:00Z", "updatedAt": "2025-05-08T14:30:00Z" } ``` For the complete transaction schema, see the [Transaction API reference](https://docs.ripple.com/products/wallet/api-docs/palisade-api/palisade-api/transactions/transactionsservice_gettransaction#transactions/transactionsservice_gettransaction/response&c=200/body). Inbound transactions and compliance For inbound transactions, the payload may include a `freezeInfo` field indicating whether funds are frozen for compliance review. See [Transaction Freeze and Compliance Controls](/products/wallet/changelogs/transaction-freeze-and-compliance-controls) for details. ### Wallet Domain You receive a webhook notification whenever a wallet transitions to a new status. | Status | Description | Terminal? | | --- | --- | --- | | `CREATED` | Wallet record created | No | | `PROVISIONING` | Wallet being set up | No | | `PROVISIONED` | Wallet ready for use | ✅ Yes | | `PROVISIONING_FAILED` | Setup failed | ✅ Yes | For the complete wallet schema, see the [Wallet API reference](https://docs.ripple.com/products/wallet/api-docs/palisade-api/palisade-api/wallets/vaultservice_getwallet#wallets/vaultservice_getwallet/response&c=200/body). ### Approval Domain You receive a webhook notification whenever an approval request is created or updated. This includes approvals for transactions, policy changes, and user management actions. #### Approval Set Status The overall approval request status: | Status | Description | Terminal? | | --- | --- | --- | | `PENDING` | Waiting for approvers to respond | No | | `MET` | Required approvals received | ✅ Yes | | `NOT_MET` | Approval rejected | ✅ Yes | | `EXPIRED` | Timed out before requirements met | ✅ Yes | | `FAILED` | Technical failure during processing | ✅ Yes | #### Individual Approval Status Each approver's response within an approval set: | Status | Description | | --- | --- | | `PROCESSING` | Approver is reviewing the request | | `APPROVED` | Approver approved the request | | `REJECTED` | Approver rejected the request | For the complete approval schema, see the [Approval API reference](https://docs.ripple.com/products/wallet/api-docs/palisade-api/palisade-api/approvals/approvalservice_getapprovalsummary#approvals/approvalservice_getapprovalsummary/t=response&c=200&path=approval). ## Best Practices ### Idempotent Processing Design your webhook handler to be idempotent. Use the resource `id` and `updatedAt` timestamp to detect and safely handle duplicate deliveries. ### Quick Acknowledgment We recommend returning a `200 OK` response within 5 seconds. Perform any heavy processing asynchronously after acknowledging receipt to avoid timeouts. ### Signature Verification Always verify the webhook signature before processing to ensure the payload is authentic. See [Manage webhooks](/products/wallet/user-interface/integrations/manage-webhooks) for verification details.