Webhook notifications

This section covers server-to-server communication that happens in case of some events

General information

As a user of the TGB API, you can subscribe to some events that happen during the donation process. TGB has implemented event notifications as HTTP Webhooks.
Security Measures:
  • payload field is AES encrypted
  • all events’ payloads will contain eventTimestamp field, so consumer may implement timestamp check, i.e. to not accept if message is older than 1 hour and/or emit an security alert in this case
Below you can find information about different types of webhooks TGB sends to subscribers.

Event: Deposit completed

When the deposit transaction is completed, The Giving Block will detect that and this notification will be sent as HTTP POST request to your notifications URL if enabled for your API user.
POST Body example:
Note: that “payload” will be passed to you in encrypted way. POST Body of the webhook will look like
{
"eventType": "DEPOSIT_TRANSACTION",
"payload": "hex-encrypted-string"
}
{
"eventType": "DEPOSIT_TRANSACTION",
"payload": {
"type": "Deposit",
"id": "8f2191c1-d28c-40ca-83b0-481828cbd8d0",
"status": "Advanced | Complete",
"timestampms": "1507913541275", // The time that the trade was executed in milliseconds
"eid": "309356152", // Transfer event id
"transactionHash": "0x12344567898909123124125125abcdefabcdefabcdef",
"currency": "ETH",
"amount": "36.00",
"organizationId": 1234567,
“eventTimestamp”: “15079132214598”,
"pledgeId": "fe497575-cf4b-4eec-b7e3-b6ce75298bdb",
"valueAtDonationTimeUSD": 45000,
"paymentMethod": "Crypto"
}
}

Explanation on some notification fields:

pledgeId is an unique identifier of a pledge. You can use this id to match the donation address you received on CreateDepositAddress API call valueAtDonationTimeUSD is a USD equivalent of transaction's amount at the time of donation. Please note that this amount is before any fees are withdrawn and should not be used for any calculation. This is primarily used for nonprofits who are HODLing and not immediately converting. This means that organizations can get approximate donation amount, in case autoconversion is disabled for the organization. paymentMethod - Enum (Crypto,Card,Stock) transactionHash is transaction hash or ID on the blockchain

Event: Transaction converted (only crypto)

When the transaction is converted, The Giving Block will detect that and this notification will be sent as HTTP POST request to your notifications URL if enabled for your API user.
POST Body example:
Note: “payload” will be passed to you in encrypted way. POST Body of the webhook will look like
{
"eventType": "TRANSACTION_CONVERTED",
"payload": "hex-encrypted-string"
}
{
"eventType": "TRANSACTION_CONVERTED",
"payload": {
"type": "Deposit",
"id": "8f2191c1-d28c-40ca-83b0-481828cbd8d0",
"status": "Advanced | Complete",
"timestampms": "1507913541275", // The time that the trade was executed in milliseconds
"eid": "309356152", // Transfer event id
"transactionHash": "0x12344567898909123124125125abcdefabcdefabcdef",
"currency": "BTC",
"amount": 1.00,
"organizationId": 1234567,
“eventTimestamp”: 15079132214598,
"convertedAt": 16079132214598,
"netValueAmount": "49000.00",
"grossAmount": "50000"
“netValueCurrency”: “USD”,
"pledgeId": "fe497575-cf4b-4eec-b7e3-b6ce75298bdb",
"valueAtDonationTimeUSD": 50000,
"pledgeId": "fe497575-cf4b-4eec-b7e3-b6ce75298bdb"
}
}

Explanation on some fields:

netValueAmount is an amount in currency returned as netValueCurrency that the nonprofit will receive as their final balance (gross donation amount - total fees).
grossAmount is an amount that is calculated during conversion of donated crypto.
valueAtDonationTimeUSD is a USD equivalent of transaction's amount at the time of donation. Please note that this amount is before any fees are withdrawn and should not be used for any calculation. This is primarily used for nonprofits who are HODLing and not immediately converting. This means that organizations can get approximate donation amount, in case autoconversion is disabled for the organization.

Example: A donor made a donation of 1 BTC, when the BTCUSD exchange rate is 50,000 USD.

  • The donation amount equals 1 BTC
  • valueAtDonationTimeUSD is 50,000 USD (amount * BTCUSD rate)
  • For example, TGB converts the donation with average exchange rate of 50,000 USD per 1 BTC.
  • Before the conversion happens, all fees are withdrawn. In this example, there is a 2% fee applied so the amount to convert to USD is 0.98 BTC (1 BTC - total fees).
  • Therefore, netValueAmount will be calculated by taking 0.98 BTC * 50,000 USD = 49,000 USD
  • So at the end of donation processing, the nonprofit organization will have 49,000 USD as their balance which will then be transferred to their bank account.

Payload decryption

To decrypt the payload you need a pair of "encryption key" and "iv" shared with you during your API credentials creation.
You can find some code snippets below. Given:
encryption key: ae97bfa25b4abcbb7d8722fc5c60747bf7687ec22d1463174f0176ad6daa96ec
encryption iv: 9663f5821170b172c51ecdd86677132f
encrypted body you've received: 87afbab0f01b956c445b00d3ab1ecf09abf18e1d1ab980641a035ec801deff07d7b708d5f2747469b86ce6216358cb695df8c7d005265aab66f678d36f01af333f6f8715569c39adabf2688cdaabac3825a0ea2b588f7e083fcf62736a3064d395bed377254302f6279ec0550f117f63c971cc9320674f535694a27fc1f034cee57433c00fbec7cdd5d2daa5b12abfd96039715c98e8e8bca401011278c5c0d3ed30f710b11a1a9b8c67773eb34f0b050acbf97b32445e5bcc32399319bd947c42d1f9ba6051f9e998dfe2c61486af0e8584529d94fc3afda941557c58725aa9c7af03577446c6d6ff2e0894cef125c0e2366a3a96f11db5a4961ee92c8262b86836f6f8debf71c80e6b36a1bfd43cff72f144560258780f8bd97100e4e4b7cb9ef45d7b61133c3b197a2e12787e439ff197e2b567a3e178b9ff7155e2663989606cdc630dd835651ad18ab88f9494efc76a74e51ff01127ac4d83b3dd6f56cea34488ff8df204d470602a40cc970f5b1cfcf6c741abe20df05b392db817903191b6fc1a1b798cc369c5a76d151cbeaa
After decryption you should get:
{
"id": "6a82de8c-d7ae-4db5-972b-588808d5f111",
"type": "Deposit",
"status": "Complete",
"timestampms": "1640774872000",
"eid": "123456789",
"transactionHash": "0ccb68148928602274f94d1119bb5b3ac705e5b567396b948e4eb4cb12ee358996",
"currency": "ETH",
"amount": 1.35,
"organizationId": 1234567,
"eventTimestamp": 1640778972000,
"pledgeId": "e4a096e9-07e4-4a34-9e52-fff72fd27260",
"valueAtDonationTimeUSD": 4159.42
}
Node.JS
PHP
Decryption code snippet:
import crypto from "crypto";
const encryptedPayloadHex = '87afbab0f01b956c445b00d3ab1ecf09abf18e1d1ab980641a035ec801deff07d7b708d5f2747469b86ce6216358cb695df8c7d005265aab66f678d36f01af333f6f8715569c39adabf2688cdaabac3825a0ea2b588f7e083fcf62736a3064d395bed377254302f6279ec0550f117f63c971cc9320674f535694a27fc1f034cee57433c00fbec7cdd5d2daa5b12abfd96039715c98e8e8bca401011278c5c0d3ed30f710b11a1a9b8c67773eb34f0b050acbf97b32445e5bcc32399319bd947c42d1f9ba6051f9e998dfe2c61486af0e8584529d94fc3afda941557c58725aa9c7af03577446c6d6ff2e0894cef125c0e2366a3a96f11db5a4961ee92c8262b86836f6f8debf71c80e6b36a1bfd43cff72f144560258780f8bd97100e4e4b7cb9ef45d7b61133c3b197a2e12787e439ff197e2b567a3e178b9ff7155e2663989606cdc630dd835651ad18ab88f9494efc76a74e51ff01127ac4d83b3dd6f56cea34488ff8df204d470602a40cc970f5b1cfcf6c741abe20df05b392db817903191b6fc1a1b798cc369c5a76d151cbeaa';
const dataEncryptionKey = Buffer.from('ae97bfa25b4abcbb7d8722fc5c60747bf7687ec22d1463174f0176ad6daa96ec', 'hex');
const dataEncryptionKeyIV = Buffer.from('9663f5821170b172c51ecdd86677132f', 'hex');
const decryptText = (hexEncodedString: string) => {
const encryptedBuffer = Buffer.from(hexEncodedString, 'hex');
const decipher = crypto.createDecipheriv('aes-256-cbc', dataEncryptionKey, dataEncryptionKeyIV);
const decrypted = decipher.update(encryptedBuffer);
return Buffer.concat([decrypted, decipher.final()]).toString();
}
console.log(decryptText(encryptedPayloadHex));
Decryption code snippet
<?php
$hexEncryptedPayload = '87afbab0f01b956c445b00d3ab1ecf09abf18e1d1ab980641a035ec801deff07d7b708d5f2747469b86ce6216358cb695df8c7d005265aab66f678d36f01af333f6f8715569c39adabf2688cdaabac3825a0ea2b588f7e083fcf62736a3064d395bed377254302f6279ec0550f117f63c971cc9320674f535694a27fc1f034cee57433c00fbec7cdd5d2daa5b12abfd96039715c98e8e8bca401011278c5c0d3ed30f710b11a1a9b8c67773eb34f0b050acbf97b32445e5bcc32399319bd947c42d1f9ba6051f9e998dfe2c61486af0e8584529d94fc3afda941557c58725aa9c7af03577446c6d6ff2e0894cef125c0e2366a3a96f11db5a4961ee92c8262b86836f6f8debf71c80e6b36a1bfd43cff72f144560258780f8bd97100e4e4b7cb9ef45d7b61133c3b197a2e12787e439ff197e2b567a3e178b9ff7155e2663989606cdc630dd835651ad18ab88f9494efc76a74e51ff01127ac4d83b3dd6f56cea34488ff8df204d470602a40cc970f5b1cfcf6c741abe20df05b392db817903191b6fc1a1b798cc369c5a76d151cbeaa';
$cipher = 'aes-256-cbc';
$hexEncryptedKey = hex2bin( 'ae97bfa25b4abcbb7d8722fc5c60747bf7687ec22d1463174f0176ad6daa96ec' );
$hexEncryptedIV = hex2bin( '9663f5821170b172c51ecdd86677132f' );
// Decrypt the payload. NOTE this requires the Open SSL module installed on your server
// Also make sure that this function is accepting a RAW encoded string and NOT a base64 encoded string
// This is easily handled by making the 4th parameter TRUE
$decrypted_data = openssl_decrypt( hex2bin( $hexEncryptedPayload ), $cipher, $hexEncryptedKey, true, $hexEncryptedIV );
echo $decrypted_data;