> ## Documentation Index
> Fetch the complete documentation index at: https://docs.primeearn.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Rewards & Postback Setup

> Configure how rewards are calculated and displayed in your app, and set up server-to-server postbacks for surveys, games, and offers.


# Rewards & Postback Setup

This guide covers two things: how to configure currency and reward display in your app, and how Prime Earn sends postback notifications to your server when users complete surveys, games, or offers.

***

## Currency & Reward Setup

You can configure how rewards are displayed in your app separately for surveys, screenouts, and games/offers.

| Setting                                        | Description                                                                                                                                     |
| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| **Currency Name**                              | Name of your in-app currency (e.g. Coins, Diamonds, Credits).                                                                                   |
| **Currency Exchange Rate**                     | How much in-app currency users receive per `$1` you earn. Example: if set to `100`, users receive 100 points per `$1`.                          |
| **Currency Exchange Rate (Screenout Rewards)** | Conversion rate specifically for users who screen out of a survey. Example: if set to `10`, users get 10 points per \$1 screenout reward value. |
| **Currency Exchange Rate (Games/Offers)**      | Conversion rate for games & offers rewards.                                                                                                     |
| **Move Decimal Point**                         | Adjusts how reward amounts are displayed to users.                                                                                              |

### Move Decimal Point Examples

| Setting    | Display      |
| ---------- | ------------ |
| No decimal | 100 points   |
| 1 decimal  | 10.0 points  |
| 2 decimals | 1.00 points  |
| 3 decimals | 0.100 points |

<Warning>
  The reward amount is always rounded to a full number. Set a minimum value of **10** to avoid rounding issues.
</Warning>

***

## Postback Setup — Surveys

When a user completes a survey action, Prime Earn sends a server-to-server postback to your configured callback URL.

### Postback Parameters

| Parameter  | Type    | Description                                                                     |
| ---------- | ------- | ------------------------------------------------------------------------------- |
| `{reward}` | Integer | Amount of in-app currency to reward to the user.                                |
| `{payout}` | Integer | Publisher payout in USD.                                                        |
| `{type}`   | Integer | Event type: `1` = complete, `2` = screenout, `3` = bonus, `4` = reconciliation. |
| `{user}`   | String  | Unique user ID.                                                                 |
| `{tx_id}`  | String  | Unique transaction ID. Process each `{tx_id}` only once.                        |
| `{subid}`  | String  | Custom subid returned back to you.                                              |

<Warning>
  All postback types are essential for accurate reward distribution, including **type = 3**. Ensure your system is configured to handle this type.
</Warning>

### When is type = 3 used?

* **Manual reward distribution** — when a user is not rewarded due to an error or technical issue, we send a manual postback (`type=3`) to ensure they receive their reward.
* **Challenge-based promotions** — for users who complete promotional challenges. This is only available for the [Surveys IFrame Integration](/surveys/iframe).
* **Pre-qualification rewards** — for users who successfully complete pre-qualification questions.

***

## Postback Setup — Games & Offers

### Postback Parameters

| Parameter                   | Type    | Description                                                                                |
| --------------------------- | ------- | ------------------------------------------------------------------------------------------ |
| `{user}`                    | String  | Unique user ID.                                                                            |
| `{tx_id}`                   | String  | Unique transaction ID. Process each `{tx_id}` only once.                                   |
| `{type}`                    | Integer | Event type: `3` = bonus/support reward, `7` = completed, `9` = reconciled, `11` = pending. |
| `{payout}`                  | Float   | Publisher payout in USD.                                                                   |
| `{platform}`                | String  | Platform where the event occurred (`mobile`, `tablet`, `desktop`).                         |
| `{offer_name}`              | String  | Display name of the offer.                                                                 |
| `{offer_hash}`              | String  | Unique identifier/hash for the offer.                                                      |
| `{task_name}`               | String  | Specific task or milestone completed in the offer.                                         |
| `{task_id}`                 | String  | Unique identifier for the task.                                                            |
| `{ip_address}`              | String  | User's IP address (IPv4 only).                                                             |
| `{user_reward_money_value}` | Float   | Monetary value of the reward before currency conversion.                                   |
| `{user_currency}`           | String  | User reward currency (e.g. `USD`, `EUR`).                                                  |
| `{reward}`                  | Integer | In-app currency rewarded to the user.                                                      |

<Warning>
  Make sure you only process each `{tx_id}` once.
</Warning>

### When is type = 3 used?

`type=3` is sent when a reward is issued outside the normal completion flow:

* **Bonus rewards** — promotions or challenge-based incentives applied to an offer.
* **Customer support rewards** — a support agent manually issues a reward to resolve a user dispute.

Credit the user immediately when you receive `type=3`. It is never reversed.

***

## Transaction ID Prefixes — Games & Offers

Every postback status is encoded in the `{tx_id}` prefix. Use the prefix to identify the event type and to correlate related postbacks for the same underlying transaction.

| Status               | Prefix   | Example `tx_id`      | Notes                                |
| -------------------- | -------- | -------------------- | ------------------------------------ |
| `COMPLETED`          | *(none)* | `93879ba3-0b72...`   | Final reward — credit the user       |
| `RECONCILED`         | `r-`     | `r-93879ba3-0b72...` | Fraud detected — do **not** credit   |
| `PENDING`            | `p-`     | `p-93879ba3-0b72...` | Awaiting verification — hold reward  |
| `PENDING_RECONCILED` | `c-`     | `c-93879ba3-0b72...` | Pending reversed — do **not** credit |

<Info>
  `PENDING` and `PENDING_RECONCILED` are newer statuses introduced alongside Credit Delay 7. Make sure your postback handler accounts for all four.
</Info>

### Matching transactions across statuses

When you receive multiple postbacks for the same event, they share the same base hash — only the prefix differs. To link them together:

<Steps>
  <Step title="Strip the prefix">
    Remove `r-`, `p-`, or `c-` from the start of the `tx_id`.
  </Step>

  <Step title="Match on the base hash">
    Use the remaining value to look up the original transaction in your database.
  </Step>
</Steps>

**Example — three postbacks, one transaction:**

| Received `tx_id`     | Base hash          |
| -------------------- | ------------------ |
| `p-93879ba3-0b72...` | `93879ba3-0b72...` |
| `r-93879ba3-0b72...` | `93879ba3-0b72...` |
| `c-93879ba3-0b72...` | `93879ba3-0b72...` |

All three refer to the same underlying transaction: `93879ba3-0b72...`

***

## Credit Delay 7 — Pending Rewards

<Info>
  Credit Delay 7 applies to **games & offers only**.
</Info>

Some offers use a 7-day credit delay. Here is how the flow works:

### Step 1 — Pending postback (immediate)

When the user completes a task, you immediately receive a `PENDING` postback:

```
https://publisher.com/postback?
  user=user_abc123&
  tx_id=tx_xyz789&
  type=11&
  status=PENDING&
  credit_delay=7
```

**Hold the reward. Do not credit the user yet.**

### Step 2 — Final postback (after 7 days)

After verification, you receive one of two outcomes:

<Tabs>
  <Tab title="COMPLETED (type=7)">
    User is verified as legitimate. Credit the reward now.

    ```
    https://publisher.com/postback?
      user=user_abc123&
      tx_id=tx_xyz789&
      type=7&
      status=COMPLETED
    ```
  </Tab>

  <Tab title="RECONCILED (type=9)">
    Fraud detected. Do not credit the user.

    ```
    https://publisher.com/unpaid-postback?
      user=user_abc123&
      tx_id=R-tx_xyz789&
      type=9&
      status=RECONCILED
    ```

    <Note>
      Reconciled postbacks include an `R-` prefix in the `tx_id`.
    </Note>
  </Tab>
</Tabs>

***

## Reconciliation & Webhooks

| Setting                     | Default | Description                                                   |
| --------------------------- | ------- | ------------------------------------------------------------- |
| **Resend failed webhooks**  | Enabled | Failed postbacks are automatically retried.                   |
| **Reconciliation webhooks** | —       | Triggered with negative values when a completion is rejected. |

***

## User Status Webhooks

Prime Earn can notify your server whenever a user is banned for fraudulent activity. Once active, Prime Earn will send a server-to-server request to the URL configured in your app settings as `webhook_url_user_status_change`.

This feature is **disabled by default**. Contact your account manager to enable it.

<Info>
  When you receive a ban notification, revoke any pending or unverified rewards and restrict the user's access to Prime Earn features.
</Info>

***

## Verifying Postback Authenticity

Each postback Prime Earn sends to your server includes a `hash` query parameter. You should validate this hash before processing the postback to ensure the request has not been tampered with.

### How the Hash Works

The hash is a **SHA-1 digest** of the full postback URL — including all query parameters except `hash` and `shash` — concatenated with a secret salt unique to your app:

```
computedHash = SHA1(fullUrlWithoutHashes + appSecurityHashSalt)
```

Your `appSecurityHashSalt` is available in your publisher dashboard. Keep it secret — never expose it in client-side code or public repositories.

<Note>
  `shash` is deprecated and will be removed in a future release. Use only `hash` for validation.
</Note>

### Validation Example (PHP)

```php theme={null}
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;

function isValidHash(Request $request): bool
{
    $appSecurityHashSalt = 'YOUR_SECRET_SALT'; // Store securely in env

    $urlWithoutHashes = fullUrlWithoutQuery($request, ['hash', 'shash']);
    $receivedHash = $request->get('hash');

    if ($receivedHash === null) {
        Log::critical('Hash is missing from the request', [
            'urlWithoutHashes' => $urlWithoutHashes,
        ]);
        return false;
    }

    $computedHash = sha1(sprintf('%s%s', $urlWithoutHashes, $appSecurityHashSalt));
    $isValidHash = $receivedHash === $computedHash;

    if (! $isValidHash) {
        Log::critical('Hash validation failed', [
            'urlWithoutHashes' => $urlWithoutHashes,
            'generatedHash'    => $computedHash,
            'requestHash'      => $receivedHash,
        ]);
    }

    return $isValidHash;
}

function fullUrlWithoutQuery(Request $request, array $keys = []): string
{
    $query = array_map(fn($v) => $v ?? '', Arr::except($request->query(), $keys));
    $question = $request->getBaseUrl() . $request->getPathInfo() === '/' ? '/?' : '?';

    return count($query) > 0
        ? $request->url() . $question . Arr::query($query)
        : $request->url();
}
```

```php theme={null}
// In your postback handler:
if (!isValidHash($request)) {
    return response('Invalid request', 400);
}

// Process the postback safely here
```

### Implementation Notes

* **Always validate the hash first.** Do not process the postback if validation fails.
* **Store the salt securely.** Use environment variables or a secrets manager — never hardcode it in publicly accessible code.
* **Log failed validations.** Logging `urlWithoutHashes`, the received hash, and the computed hash makes it straightforward to diagnose misconfigurations or detect tampering.
* The logic handles optional query parameters correctly — only `hash` and `shash` are excluded from the computation.

<Tip>
  **If your integration is already live**, do not reject postbacks immediately when a hash fails. Instead, log the relevant values (`urlWithoutHashes`, received hash, computed hash) and use those logs to debug without disrupting live traffic.
</Tip>

***

## IP Whitelist

Ensure your server accepts postback requests from these Prime Earn IP addresses only. Reject all other sources to prevent reward fraud.

```
168.119.57.82
49.12.33.196
49.13.14.251
```
