Callbacks
When a user completes an offer surfaced through the Eligibility API, TapResearch notifies your server with a server-to-server postback. Validate every callback before you reward the user.
Server-to-Server Postback
The server-to-server postback is a GET request that TapResearch sends to your callback URL immediately after a user earns a reward. The reward details are passed as query parameters, and an HMAC-MD5 signature (sig) lets you verify the request originated from TapResearch.
Important: With server-to-server callbacks your app is responsible for notifying users of the rewards they receive — TapResearch does not notify users with this method.
Update Callback URL
Set or update your callback URL in the "Edit App" section of the Publisher Dashboard.
URL requirements:
- No spaces or special characters
- Must return a 2xx response code to be considered valid
Sample Request
https://your-callback-url.example.com/postback?uid=developers%40tapresearch.com&tid=777ca23551a4a9173920c22e1ed7f4f3&cpid=tap_37939e4ede350f3a8d5149d2fcaa025e&payout_amount=191&payout_currency=gold&revenue=0.5&payout_type=3&sig=42cbd66af5b670bed293d9b01c06d3c4
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| uid | String | Persistent unique identifier for this user. |
| tid | String | Transaction ID or click ID. This value will not be unique if the user completed multiple surveys in a single session. Use cpid for deduping purposes. |
| cpid | String | Unique survey complete identifier. We recommend that you store and check against this value to ensure you reward the user only once per survey complete. |
| payout_amount | Integer | Amount of currency earned by this user. |
| payout_currency | String | The type of currency the user earned. |
| revenue | Decimal | Amount you will be paid for this survey complete, in USD. |
| payout_type | Integer | The action that the user was rewarded for. 0 - Profile Complete, 3 - Survey Rewarded, 9 - Quick Question Completed. |
| sig | String | The URL signature: an HMAC-MD5 generated from the query string minus the sig parameter. See Signature Validation below. |
The callback may include additional parameters beyond those listed here, and more may be added over time. This is expected — the signature always covers the entire query string, so validate against whatever you actually receive rather than a fixed list of fields (see Signature Validation).
Callback Testing
Use the Test Callback button in the dashboard to generate a test completion that fires a callback to your specified URL.
Best practice: Test callbacks before deploying to production.
Test callbacks use fixed currency values. Commercial survey values will vary.
Signature Validation
For security, every callback request includes an HMAC-MD5 signature (sig) generated from the query string. Validate it on every request before you reward a user.
Sign the entire query string exactly as you receive it, minus sig — don't rebuild it from a fixed list of parameters. The signature covers every parameter present, so hashing whatever arrives (as the steps and code below do) stays correct even as parameters are added.
Grab your API secret from your main dashboard. Example: 26dcc0fc7b6208fdfeffaf19f627cb4a
- Start with the incoming callback request, for example:
https://your-callback-url.example.com/postback?uid=developers%40tapresearch.com&tid=777ca23551a4a9173920c22e1ed7f4f3&cpid=tap_37939e4ede350f3a8d5149d2fcaa025e&payout_amount=191&payout_currency=gold&revenue=0.5&payout_type=3&sig=42cbd66af5b670bed293d9b01c06d3c4 - Isolate the query string, leaving out the question mark.
- Strip out the
sigparameter, including the leading ampersand (&). - URL-decode the remaining query string.
- Run your API secret and the decoded query string through an HMAC-MD5 generator.
- Compare your generated HMAC against the
sigparameter value. If they match, record the complete and reward the user.
- Ruby
- PHP
- Java
# Sample request URL
url = "https://your-callback-url.example.com/postback?uid=developers%40tapresearch.com&tid=777ca23551a4a9173920c22e1ed7f4f3&cpid=tap_37939e4ede350f3a8d5149d2fcaa025e&payout_amount=191&payout_currency=gold&revenue=0.5&payout_type=3&sig=42cbd66af5b670bed293d9b01c06d3c4"
# Isolate query string
query_string = url.gsub(/^(.*?)\?/, "")
# Strip out the sig parameter
stripped_query_string = query_string.gsub(/&sig.*/, "")
# Decode URL
decoded = URI.decode_www_form_component(stripped_query_string)
# Generate HMAC-MD5
api_secret = "26dcc0fc7b6208fdfeffaf19f627cb4a"
digest = OpenSSL::Digest.new("md5")
md5 = OpenSSL::HMAC.hexdigest(digest, api_secret, decoded)
puts md5 # 42cbd66af5b670bed293d9b01c06d3c4
<?php
# Sample request URL
$url = 'https://your-callback-url.example.com/postback?uid=developers%40tapresearch.com&tid=777ca23551a4a9173920c22e1ed7f4f3&cpid=tap_37939e4ede350f3a8d5149d2fcaa025e&payout_amount=191&payout_currency=gold&revenue=0.5&payout_type=3&sig=42cbd66af5b670bed293d9b01c06d3c4';
# Isolate query string
$query_string = parse_url($url, PHP_URL_QUERY);
# Strip out the sig parameter
$stripped_query_string = substr($query_string, 0, strpos($query_string, 'sig') - 1);
# Decode URL
$decoded = urldecode($stripped_query_string);
# Generate HMAC-MD5
$api_secret = '26dcc0fc7b6208fdfeffaf19f627cb4a';
$md5 = hash_hmac('md5', $decoded, $api_secret);
echo $md5; # 42cbd66af5b670bed293d9b01c06d3c4
?>
private static final String API_SECRET = "26dcc0fc7b6208fdfeffaf19f627cb4a";
private static final String ALGO = "HmacMD5";
try {
// URL
String urlString = "https://your-callback-url.example.com/postback?uid=developers%40tapresearch.com&tid=777ca23551a4a9173920c22e1ed7f4f3&cpid=tap_37939e4ede350f3a8d5149d2fcaa025e&payout_amount=191&payout_currency=gold&revenue=0.5&payout_type=3&sig=42cbd66af5b670bed293d9b01c06d3c4";
// Generate HMAC-MD5
Mac mac = Mac.getInstance(ALGO);
SecretKeySpec key = new SecretKeySpec(API_SECRET.getBytes(StandardCharsets.UTF_8), ALGO);
mac.init(key);
// Isolate query string and remove sig parameter
String queryString = urlString.substring(urlString.indexOf("?") + 1);
queryString = queryString.substring(0, queryString.indexOf("&sig=")) + queryString.substring(queryString.indexOf("&sig=") + 37);
// Decode URL
String decode = URLDecoder.decode(queryString, StandardCharsets.UTF_8);
byte[] bytes = mac.doFinal(decode.getBytes(StandardCharsets.UTF_8));
String md5 = DatatypeConverter.printHexBinary(bytes).toLowerCase();
System.out.println(md5); // 42cbd66af5b670bed293d9b01c06d3c4
} catch (Exception e) {
e.printStackTrace();
}
Whitelisted IP Addresses
To further harden your endpoint, restrict incoming callback requests to the following TapResearch source IP addresses:
| IP Address |
|---|
| 34.198.225.203 |
| 3.88.121.21 |
| 3.89.214.250 |
| 3.92.129.242 |
Retries
If a callback fails, our system continues retrying to send the reward for 48 hours OR until a 2xx response code is returned.