Skip to main content
Version: 3.x

Handling rewards

TapResearch reports every reward to your backend through a server-to-server postback. Because the Survey Feed API has no in-app SDK surface, only the server-to-server postback applies here.

Server-to-server postbacks​

The server-to-server postback is a GET request that TapResearch sends to your postback URL as soon as a user earns a reward. The reward details are passed as query parameters, and an HMAC-MD5 signature (sig) lets you verify the request came from TapResearch.

Important: With server-to-server postbacks your app is responsible for notifying users of the rewards they receive — TapResearch does not notify users with this method.

Set your postback URL​

In the Publisher Dashboard, open your app's Settings tab and select API settings. Enter your URL in Rewards/monetization postback URL under Server-to-server postbacks.

Rewards/monetization postback URL field and Test rewards postback button under Server-to-server postbacks in the Publisher Dashboard

URL requirements:

  • Must begin with https://
  • No spaces or special characters, other than the placeholders described in Renaming parameters
  • Must respond within 5 seconds. The dashboard test requires HTTP 200; live postbacks accept any 2xx response.

Testing your postback URL​

Run Test rewards postback before saving or updating the URL. The test must return HTTP 200 before the dashboard allows you to save.

Sample requests​

https://your-postback-url.example.com/postback?api_token=your-api-token&cpid=tap_37939e4ede350f3a8d5149d2fcaa025e&ip_address=203.0.113.42&offer_identifier=8f14e45fceea167a5a36dedd4bea2543&payout_amount=191&payout_currency=gold&payout_type=3&revenue=0.5&tid=777ca23551a4a9173920c22e1ed7f4f3&uid=developers%40tapresearch.com&sig=435ad87fb971836540ebc3a320efe9f1

Parameters​

ParameterTypeDescription
api_tokenStringYour app's API token.
cpidStringUnique identifier for the reward. Use it to ensure each reward is credited only once.
didStringDevice identifier, if available.
ip_addressStringThe user's IP address, if available.
offer_identifierStringIdentifier of the TapResearch offer that issued the reward.
payout_amountIntegerAmount of currency earned by this user.
payout_currencyStringThe name of the currency the user earned.
payout_typeIntegerThe action that the user was rewarded for. 0 - Profile Complete, 3 - Survey Rewarded, 9 - Quick Question Completed (SDK only), 10 - Bonus Bar Reward.
revenueDecimalAmount you will be paid for this reward, in USD.
tidStringTransaction ID (click ID) of the user's session. Use cpid, not tid, to identify a reward.
uidStringPersistent unique identifier for this user.
sigStringGET requests only, always the last parameter: an HMAC-MD5 of the query string before it. See Signature validation.
Note

Postbacks may include additional fields. Validate the signature against the entire query string you receive, not a fixed list of fields.

Renaming parameters​

If your postback URL points at a tracking or affiliate network that expects its own parameter names, put placeholders in the URL's query string. TapResearch fills each placeholder with the matching value and sends that value only under your parameter name.

PlaceholderFilled with
{UID}uid
{DID}did
{TID}tid
{CPID}cpid
{API_TOKEN}api_token
{PAYOUT_AMOUNT}payout_amount
{PAYOUT_CURRENCY}payout_currency
{REVENUE}revenue
{PAYOUT_TYPE}payout_type
{IP_ADDRESS}ip_address

Postback URL you save:

https://your-postback-url.example.com/postback?clickid={TID}&sum={REVENUE}&goal={PAYOUT_TYPE}&custom_field2={PAYOUT_AMOUNT}

Request you receive:

https://your-postback-url.example.com/postback?clickid=777ca23551a4a9173920c22e1ed7f4f3&sum=0.5&goal=3&custom_field2=191&api_token=your-api-token&cpid=tap_37939e4ede350f3a8d5149d2fcaa025e&ip_address=203.0.113.42&offer_identifier=8f14e45fceea167a5a36dedd4bea2543&payout_currency=gold&uid=developers%40tapresearch.com&sig=a86c2ce25c178aa375b82e0d3b51e93a

How placeholders work:

  • Placeholders are case-sensitive and go in parameter values.
  • Parameters you don't rename are still sent under their standard names.
  • Parameters with unknown placeholders, literal braces, or unavailable values are omitted.
  • Placeholders apply to GET postbacks only.

sig remains the last parameter and covers the entire query string. Don't name a custom parameter sig. See Signature validation.

Use Test rewards postback to try a URL with placeholders before you save it.

Security​

GET postbacks are signed with sig, as described below.

Signature validation​

Every GET postback ends with a sig parameter: an HMAC-MD5 of the query string that comes before it. 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, including your own static and renamed parameters, so hashing whatever arrives (as the steps and code below do) stays correct as parameters are added.

Use your app's API Secret, available in its settings in the Publisher Dashboard. The examples use the sample secret 26dcc0fc7b6208fdfeffaf19f627cb4a.

  1. Start with the incoming postback request, for example:

    https://your-postback-url.example.com/postback?api_token=your-api-token&cpid=tap_37939e4ede350f3a8d5149d2fcaa025e&ip_address=203.0.113.42&offer_identifier=8f14e45fceea167a5a36dedd4bea2543&payout_amount=191&payout_currency=gold&payout_type=3&revenue=0.5&tid=777ca23551a4a9173920c22e1ed7f4f3&uid=developers%40tapresearch.com&sig=435ad87fb971836540ebc3a320efe9f1
  2. Isolate the query string: everything after the ?.

  3. Remove &sig= and the signature after it. sig is always the last parameter.

  4. Percent-decode the rest, preserving literal + characters. The examples below use decoders that do this.

  5. Run your API secret and the decoded query string through an HMAC-MD5 generator, with lowercase hex output.

  6. Compare your result with the sig value, using a constant-time comparison. If they match, record the reward and credit the user.

require "openssl"
require "uri"

# Sample request URL (in Rails, read the raw query with request.query_string)
url = "https://your-postback-url.example.com/postback?api_token=your-api-token&cpid=tap_37939e4ede350f3a8d5149d2fcaa025e&ip_address=203.0.113.42&offer_identifier=8f14e45fceea167a5a36dedd4bea2543&payout_amount=191&payout_currency=gold&payout_type=3&revenue=0.5&tid=777ca23551a4a9173920c22e1ed7f4f3&uid=developers%40tapresearch.com&sig=435ad87fb971836540ebc3a320efe9f1"

# Isolate the query string and split off sig, which is always last
query_string = url.split("?", 2).last
signature = query_string[/&sig=([0-9a-f]+)\z/, 1]
unsigned_query = query_string.sub(/&sig=[0-9a-f]+\z/, "")

# Percent-decode only: "+" stays "+"
decoded = URI::Parser.new.unescape(unsigned_query)

# Generate HMAC-MD5
api_secret = "26dcc0fc7b6208fdfeffaf19f627cb4a"
expected = OpenSSL::HMAC.hexdigest("MD5", api_secret, decoded)

puts OpenSSL.secure_compare(expected, signature) # true

IP allowlist​

To further harden your endpoint, you can restrict incoming postback 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 postback fails, our system retries sending the reward for 48 hours OR until a 2xx response code is received.

Survey outcome parameter​

For every survey reward postback generated via the Survey Feed API (payout_type 3), the survey_outcome parameter is included — an integer representing the participant's final status:

ValueStatusDescription
1CompleteThe participant successfully completed the survey.
2DisqualifiedThe participant was screened out based on targeting requirements.
3Over QuotaThe survey reached its quota while the participant was in progress.

Postbacks only fire for revenue-generating matches. If a participant is disqualified or the survey reaches its quota, a postback is sent only when that outcome results in a partial reward (as configured in your App Settings). If no revenue is generated for the event, no postback is triggered.