# Server-to-Server (S2S) Callback Configuration

You can configure the S2S callback for the offerwall in the dashboard inside the Offerwall's overview section.

## 1. Setup Callback URL

When a user has earned a reward by completing an offer, we fire an HTTP GET request to the provided callback URL. The following query parameters will be part of the request.

{% hint style="info" %}
**Example callback setup:**

**Callback URL set by you:** <http://www.example.com/payments/offers/pubscale>

**Request sent from us:** HTTP GET <http://www.example.com/payments/offers/pubscale?user\\_id=\\>\<user\_id>\&value=\<value>\&token=\<token>\&signature=\<signature>
{% endhint %}

```url
<callback_url>?user_id=<user_id>&value=<value>&token=<token>&signature=<signature>      
//Example http://www.example.com/payments/offers/pubscale?user_id=<user_id>&value=<value>&token=<token>&signature=<signature>
```

<table><thead><tr><th width="158">Query Params</th><th>Description</th></tr></thead><tbody><tr><td>user_id</td><td>The 'unique_id' set while initializing the SDK.</td></tr><tr><td>value</td><td>The decimal value of the reward earned by the user.</td></tr><tr><td>token</td><td>A token that uniquely represents the transaction.</td></tr><tr><td>signature</td><td>Hash of the above values to verify the request (more info below).</td></tr></tbody></table>

## 2. Server Response

<mark style="color:purple;">Responding to the callback URL with status codes between and including the values 200 to 299 will mark the callback as successfully delivered.</mark>

In the event of the server not responding with any of the aforementioned status codes, the request will be **retried 6 times** at different intervals. You can utilize the unique token sent in the request to avoid rewarding the user multiple times for the same callback.

## 3. Optional Parameters for fraud detection/prevention

### 3.1. Hash validation

The value sent in the signature parameter can be used to validate the identity of the origin of the request. The value is an MD5 hash of the template below. The secret key is an additional key that will be provided along with the APP API KEY.

{% tabs %}
{% tab title="PHP" %}

```php
function calculateHash() {
	
	$user = $_GET['user_id'];
	$token = $_GET['token'];
	$value = $_GET['value'];

	$template = <secret_key>. "." . $user . "." . (int)$value . "." $token;

	return calculateMD5($template);
}

function calculateMD5($data) {
	return hash('md5', $data);
}

$hash = $_GET['signature'];

if ($hash != calculateHash()) {
	return false
}
```

{% endtab %}

{% tab title="NodeJs" %}

```javascript
const md5 = require('md5')
  
const template = `${<secret_key>}.${<user_id>}.${Math.trunc(<value>)}.${<token>}`
const hash = md5(template)

if(signature != hash) {
    return false
}

```

{% endtab %}

{% tab title="Python" %}

```python
import hashlib

template = '{secret_key}.{user_id}.{value}.{token}'.format(secret_key=<secret_key>,user_id=<user_id>,value=int(<value>),token=<token>)
hash = hashlib.md5(template.encode('utf-8')).hexdigest()

if hash != <signature>:
    return false            
```

{% endtab %}

{% tab title="Golang" %}

```go
template := fmt.Sprintf("%s.%s.%d.%s", <secret_key>, <user_id>, <int({value>), <token>)
hash := toMD5(template)

  if hash != {signature} {
        return errors.New("invalid signature")
  }

func toMD5(text string) string {
  algorithm := md5.New()
  algorithm.Write([]byte(text))
  return hex.EncodeToString(algorithm.Sum(nil))
}

```

{% endtab %}
{% endtabs %}

### Example

secret\_key = `fa072672-d432-11c4-885a-EB1CdEc4Bb13`\
user\_id = `30356439-8d15-4f47-B133-010a37C19eBD`\
value = `100.1234`\
token = `525a5B8e-512b-441A-a10B-72d218c370e5`

Final format = `fa072672-d432-11c4-885a-EB1CdEc4Bb13.30356439-8d15-4f47-B133-010a37C19eBD.100.525a5B8e-512b-441A-a10B-72d218c370e5`

### Steps to validate the value of the hash

1. Concatenate the values in the above format.
2. Make sure to convert the value parameter from decimal to integer.
3. Calculate the MD5 hash of the concatenated value.
4. Build Hex encode of the generated value.
5. Verify if the calculated value is equal to the value sent in the signature parameter.

{% hint style="info" %}
As the value of the secret key will only be known to you and PubScale’s server, the hash cannot be generated by a fraudulent third party.
{% endhint %}

### 3.2. IP Whitelisting

You can restrict the callbacks to be accepted only from our sever IP address(es). Please whitelist the following IP(s) and regularly check back to find possible changes&#x20;

```
34.100.236.68

//Last updated at: Jan 23, 2024
```
