Server to Server Callback

Learn how to reward your users based on our server to server callbacks

A Guide to Server to Server Callbacks

In this article, you will learn how to properly set up your callback links. Please note that we can only give rough instructions on how to set up the callbacks on your end, as everybody has different systems for receiving and processing callbacks.

Purpose of Callbacks

When a user completes a survey or gets a screenout reward, we send a callback. This is how we tell your sercver that one of your users has successfully completed a survey. You can then use the information to reward your users. You can customize the callback link to include all of the parameters you need to reward your users. To achieve this, you'll need to customize your callback URL with the desired parameters.

Step by Step Guide for setting up your Callbacks

First of all, make sure you have created your app within the BitLabs dashboard. This requires a verified BitLabs Account, which you can sign up for here if you haven't already. In the top right corner, you'll see a field to configure your postback link. That may be where you found a link to this article ;). In this field, you can start out with a link to the script you need us to call when a user has completed an offer.

To understand callbacks a little bit better, take a look at this final callback link we have sent out:

https://publisher.com/complete?uid=8cc877ee-af19-488d-b28d-216fb866b996&val=500

In order to achieve this callback, here's what we've set up in the BitLabs Dashboard:

Dashboard Callback Parameters

As you can see, we have added the needed variables as they are specified below the callback form on your dashboard. It is really important to stick to the right format. Common mistakes are to not include [] or to forget about %%. Always use the full variable including [%%] in your callback link on our dashboard. To see if your callback is working, use the callback testing button to send a callback to a specific user with a value of your choice. We are filling out the parameters automatically. Make sure that you are using these variables in your callback, otherwise you cannot edit them in the testing tool.

Standard Parameters

Parameter Type Description
[%VAL%] Float User Reward in App Currency. You can configure it in the Settings.
[%UID%] String Unique User Identifier, passed by publisher.
[%TYPE%] String Type of the callback ("COMPLETE" or "SCREENOUT").
[%TX%] Integer Transaction Id. Use this to prevent double booking.
[%RAW%] Float Complete payment in USD, paid to the publisher.
[%RAT%] Integer Survey Rating from 0 to 5
[%NET%] String Internal Survey Source/Mediation Layer
[%LOI%] Integer Length of the Survey in minutes.
[%DIF%] String Difficulty ("easy", "medium" or "hard") of the survey.
[%CAT%] String Category of the Survey.
[%COUNTRY%] String The Country the User took the survey from as ISO Code. (Example: US, DE, FR)
TAG Object Any parameter you've attached to the opening link.
&hash=[Hash] String Always attached: Hash of the complete URI (HEX encoded SHA-1 HMAC) with the App Secret.

Additional Parameters

You can attach all the variables specified in the table on your dashboard. Sometimes you may need additional information with your callback. In this case, you can just add custom variables to the BitLabs link you are sending your users to. We will pass the same parameter back with the callback. Of course, this is optional. Let's say you want to include the fact that your users are doing surveys on an android device in your callback. Within your app, you would attach &source=android to your BitLabs link. This will automatically be added to the callback we send, like this:

https://publisher.com/complete?uid=8cc877ee-af19-488d-b28d-216fb866b996&val=500&source=android

Please note that we will not be interpreting your custom variables, meaning what you send in is what is sent back to you.

Hashing

In order to make callbacks safe, we are we append a "&hash=[HASH] at the end of each callback. This is an important feature for you to make sure that the callback, which you use as a base to reward your users, is coming from BitLabs and is not fake. This hash consists of a HEX encoded SHA1 HMAC. The whole URL is hashed with the secret key of the App. By checking the hash, you can be sure that the postback was actually sent by us and that it is legit.

Example

Callback URL: "https://publisher.com/complete?uid=8cc877ee-af19-488d-b28d-216fb866b996&val=500"

App Secret: "JLOIAUNMHFli7ZJOQVEzm98rzqnm9"

Hash: "dbcd6bb8ca677344592842a52b4fca9bec36cd4b"

Final Callback sent to the publisher:

https://publisher.com/complete?uid=8cc877ee-af19-488d-b28d-216fb866b996&val=500&hash=dbcd6bb8ca677344592842a52b4fca9bec36cd4b

Hashing Code Examples

These code samples are meant to give you an idea of how to validate hashes. It can also be used as an example of how to handle callbacks in general.

NodeJS
const crypto = require('crypto');

function checkHash(url, secretKey) {
  const splitUrl = url.split('&hash=');
  const hmac = crypto.createHmac('sha1', secretKey);
  hmac.write(splitUrl[0]);
  hmac.end();
  return splitUrl[1] === hmac.read().toString('hex');
}

const secretKey = '';
const url = 'http://url.com?param1=foo&param2=bar&hash=3171f6b78e06cadcec4c9c3b15f858b8400e8738';
console.log(checkHash(url, secretKey)); 
PHP
<?php
// This has to be your App's secret key that you can find on the Dashboard
$secret_key = "";
// Get the currently active http protocol
$protocol = isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] === "on" ? "https" : "http";
// Build the full callback URL
// Example: https://url.com?param1=foo&param2=bar&hash=3171f6b78e06cadcec4c9c3b15f858b8400e8738
$url = "$protocol://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
// Save all query parameters of the callback into the $params array
$url_components = parse_url($url);
parse_str($url_components["query"], $params);
// Get the callback URL without the "hash" query parameter
// Example: https://url.com?param1=foo&param2=bar
$url_val = substr($url, 0, -strlen("&hash=$params[hash]"));
// Generate a hash from the complete callback URL without the "hash" query parameter
$hash = hash_hmac("sha1", $url_val, $secret_key);

//Check if the generated hash is the same as the "hash" query parameter
if ($params["hash"] === $hash) {
  echo "valid";
} else {
  echo "invalid";
}
C#
using System;
using System.Web;
using System.Text;
using System.Security.Cryptography;
using System.Collections.Specialized;

public class Program {
  public static void Main() {
    string secretKey = "";
    string url = "http://url.com?param1=foo&param2=bar&hash=3171f6b78e06cadcec4c9c3b15f858b8400e8738";
    if (IsURLHashValid(url, secretKey)) {
      Console.WriteLine("valid");
    } else {
      Console.WriteLine("invalid");
    }
  }
  
  public static bool IsURLHashValid(string url, string secretKey) {
    Uri uri = new Uri(url);
    NameValueCollection queryString = HttpUtility.ParseQueryString(uri.Query);
    string urlHash = queryString.Get("hash");
    queryString.Remove("hash");
    string baseURL = uri.GetLeftPart(UriPartial.Authority);
    string urlValue = queryString.Count > 0 ? String.Format("{0}?{1}", baseURL, queryString) : baseURL;
    return urlHash == CreateHash(urlValue, secretKey);
  }
  
  public static string CreateHash(string urlValue, string secretKey) {
    HMACSHA1 hmac = new HMACSHA1(Encoding.UTF8.GetBytes(secretKey));
    byte[] buffer = Encoding.UTF8.GetBytes(urlValue);
    return BitConverter.ToString(hmac.ComputeHash(buffer)).Replace("-", "").ToLower();
  }
}

Ready to get started?