Validate Requests

Fireblocks sends events to your webhook endpoint URL(s) associated with the workspace, as part of a POST request with a JSON payload.

Validation

You can validate Fireblocks webhook events by validating the signature attached in the request header:

Fireblocks-Signature: Base64(RSA512(_WEBHOOK_PRIVATE_KEY_, SHA512(eventBody)))

To validate the signature in Production workspaces, please use the public key below:

-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0+6wd9OJQpK60ZI7qnZG jjQ0wNFUHfRv85Tdyek8+ahlg1Ph8uhwl4N6DZw5LwLXhNjzAbQ8LGPxt36RUZl5 YlxTru0jZNKx5lslR+H4i936A4pKBjgiMmSkVwXD9HcfKHTp70GQ812+J0Fvti/v 4nrrUpc011Wo4F6omt1QcYsi4GTI5OsEbeKQ24BtUd6Z1Nm/EP7PfPxeb4CP8KOH clM8K7OwBUfWrip8Ptljjz9BNOZUF94iyjJ/BIzGJjyCntho64ehpUYP8UJykLVd CGcu7sVYWnknf1ZGLuqqZQt4qt7cUUhFGielssZP9N9x7wzaAIFcT3yQ+ELDu1SZ dE4lZsf2uMyfj58V8GDOLLE233+LRsRbJ083x+e2mW5BdAGtGgQBusFfnmv5Bxqd HgS55hsna5725/44tvxll261TgQvjGrTxwe7e5Ia3d2Syc+e89mXQaI/+cZnylNP SwCCvx8mOM847T0XkVRX3ZrwXtHIA25uKsPJzUtksDnAowB91j7RJkjXxJcz3Vh1 4k182UFOTPRW9jzdWNSyWQGl/vpe9oQ4c2Ly15+/toBo4YXJeDdDnZ5c/O+KKadc IMPBpnPrH/0O97uMPuED+nI6ISGOTMLZo35xJ96gPBwyG5s2QxIkKPXIrhgcgUnk tSM7QYNhlftT4/yVvYnk0YcCAwEAAQ== -----END PUBLIC KEY-----

To validate the signature in Sandbox workspaces, please use the public key below:

-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw+fZuC+0vDYTf8fYnCN6 71iHg98lPHBmafmqZqb+TUexn9sH6qNIBZ5SgYFxFK6dYXIuJ5uoORzihREvZVZP 8DphdeKOMUrMr6b+Cchb2qS8qz8WS7xtyLU9GnBn6M5mWfjkjQr1jbilH15Zvcpz ECC8aPUAy2EbHpnr10if2IHkIAWLYD+0khpCjpWtsfuX+LxqzlqQVW9xc6z7tshK eCSEa6Oh8+ia7Zlu0b+2xmy2Arb6xGl+s+Rnof4lsq9tZS6f03huc+XVTmd6H2We WxFMfGyDCX2akEg2aAvx7231/6S0vBFGiX0C+3GbXlieHDplLGoODHUt5hxbPJnK IwIDAQAB -----END PUBLIC KEY-----

Check event objects

Each event is structured as an object with a type and data sub object that holds the transaction id, as well as other related information. Your endpoint must check the event type and parse the payload of each event.

Example: transaction created webhook
{ "type": "TRANSACTION_CREATED", "tenantId”: ".........-.....-....-....-...........", "timestamp": 1679651214621, "data": { "id": "........-....-....-....-............", "createdAt": 1679651104380, "lastUpdated": 1679651104380, "assetId": "WETH_TEST3", "source": { "id": "0", "type": "VAULT_ACCOUNT", "name": "Main", "subType": "" }, "destination": { "id": "12", "type": "VAULT_ACCOUNT", "name": "MintBurn", "subType": "" }, "amount": 0.001, "sourceAddress": "", "destinationAddress": "", "destinationAddressDescription": "", "destinationTag": "", "status": "SUBMITTED", "txHash": "", "subStatus": "", "signedBy": [], "createdBy": ".........-.....-....-....-...........", "rejectedBy": "", "amountUSD": null, "addressType": "", "note": "", "exchangeTxId": "", "requestedAmount": 0.001, "feeCurrency": "ETH_TEST3", "operation": "TRANSFER", "customerRefId": null, "amountInfo": { "amount": "0.001", "requestedAmount": "0.001" }, "feeInfo": {}, "destinations": [], "externalTxId": null, "blockInfo": {}, "signedMessages": [], "assetType": "ERC20" } }
{ "eventType": "TRANSACTION_CREATED", "tenantId”: ".........-.....-....-....-...........", "resourceId”: ".........-.....-....-....-...........", "eventVersion”: 1, "timestamp": 1679651214621, "data": { "id": "........-....-....-....-............", "createdAt": 1679651104380, "lastUpdated": 1679651104380, "assetId": "WETH_TEST3", "source": { "id": "0", "type": "VAULT_ACCOUNT", "name": "Main", "subType": "" }, "destination": { "id": "12", "type": "VAULT_ACCOUNT", "name": "MintBurn", "subType": "" }, "amount": 0.001, "sourceAddress": "", "destinationAddress": "", "destinationAddressDescription": "", "destinationTag": "", "status": "SUBMITTED", "txHash": "", "subStatus": "", "signedBy": [], "createdBy": ".........-.....-....-....-...........", "rejectedBy": "", "amountUSD": null, "addressType": "", "note": "", "exchangeTxId": "", "requestedAmount": 0.001, "feeCurrency": "ETH_TEST3", "operation": "TRANSFER", "customerRefId": null, "amountInfo": { "amount": "0.001", "requestedAmount": "0.001" }, "feeInfo": {}, "destinations": [], "externalTxId": null, "blockInfo": {}, "signedMessages": [], "assetType": "ERC20" } }
Example: transaction status updated webhook
{ "type": "TRANSACTION_STATUS_UPDATED", "tenantId”: ".........-.....-....-....-...........", "timestamp": 1679651214621, "data": { "id": "........-....-....-....-............", "createdAt": 1680014718734, "lastUpdated": 1680014729691, "assetId": "TRX_USDT", "source": { "id": "", "type": "UNKNOWN", "name": "External", "subType": "" }, "destination": { "id": "2107", "type": "VAULT_ACCOUNT", "name": "Main", "subType": "" }, "amount": 370, "networkFee": 27.2559, "netAmount": 370, "sourceAddress": "", "destinationAddress": "", "destinationAddressDescription": "", "destinationTag": "", "status": "COMPLETED", "txHash": "e9e1asdade125be06638c8675fdsfsdc79594dd45ff095b7683c3f03b81a9389684", "subStatus": "CONFIRMED", "signedBy": [], "createdBy": "", "rejectedBy": "", "amountUSD": 0, "addressType": "", "note": "", "exchangeTxId": "", "requestedAmount": 370, "feeCurrency": "TRX", "operation": "TRANSFER", "customerRefId": "........-....-....-....-............", "numOfConfirmations": 1, "amountInfo": { "amount": "370", "requestedAmount": "370", "netAmount": "370", "amountUSD": null }, "feeInfo": { "networkFee": "27.2559" }, "destinations": [], "externalTxId": null, "blockInfo": { "blockHeight": "49800684", "blockHash": "0000000002f7e5ece07efd8dfnjngfh76dda5f2645a9aba5e6h4534ba1bc7d97a8e2" }, "signedMessages": [], "amlScreeningResult": { "screeningStatus": "BYPASSED", "bypassReason": "PASSED_BY_POLICY", "timestamp": 1680014729455 }, "assetType": "TRON_TRC20" } }
{ "eventType": "TRANSACTION_STATUS_UPDATED", "tenantId”: ".........-.....-....-....-...........", "resourceId”: ".........-.....-....-....-...........", "eventVersion”: 1, "timestamp": 1679651214621, "data": { "id": "........-....-....-....-............", "createdAt": 1679651104380, "lastUpdated": 1679651104380, "assetId": "WETH_TEST3", "source": { "id": "0", "type": "VAULT_ACCOUNT", "name": "Main", "subType": "" }, "destination": { "id": "12", "type": "VAULT_ACCOUNT", "name": "MintBurn", "subType": "" }, "amount": 0.001, "sourceAddress": "", "destinationAddress": "", "destinationAddressDescription": "", "destinationTag": "", "status": "SUBMITTED", "txHash": "", "subStatus": "", "signedBy": [], "createdBy": ".........-.....-....-....-...........", "rejectedBy": "", "amountUSD": null, "addressType": "", "note": "", "exchangeTxId": "", "requestedAmount": 0.001, "feeCurrency": "ETH_TEST3", "operation": "TRANSFER", "customerRefId": null, "amountInfo": { "amount": "0.001", "requestedAmount": "0.001" }, "feeInfo": {}, "destinations": [], "externalTxId": null, "blockInfo": {}, "signedMessages": [], "assetType": "ERC20" } }

Response

The Fireblocks server will look for a response to confirm the webhook notification was received. All webhook events should receive an HTTP-200 (OK) response.

If no response is received, Fireblocks will resend the 5xx request several more times. The retry schedule (in seconds) is 5, 15, 35, 75, 155, 315, 635, 1275, 2555.