BitsOffers Documentation
Everything you need to monetize your website, faucet or app with the BitsOffers offerwall: embed code, real-time postbacks, security and API. Integration takes only a few minutes.
Add your website
To integrate the offerwall you first have to add your website. Once it is added you will receive an API KEY and a SECRET KEY.
- Sign in to your BitsOffers account.
- Click Add Website (top bar or sidebar).
- Enter your website name, domain and platform type.
- Set your currency name in plural (Points, Coins, Tokens…), the number of decimals (up to 2) and the exchange rate: how many of your currency units a user earns for every 1 USD.
- Set your Postback URL. We call it every time a user completes an offer so you can credit the reward (see Postbacks).
- Done! Our team reviews your website. Meanwhile you can continue with the integration.
Offerwall integration
The offerwall adapts to any screen and shows your users offers, surveys, games, PTC ads, shortlinks and more — all in one place. Your API key is in Websites → your site → API keys.
Offerwall code
Paste this code where you want to show the offerwall:
<iframe src="https://bitsoffers.com/offerwall?userid=[USER_ID]&key=[API_KEY]"
style="width:100%;height:800px;border:0;padding:0;margin:0;"
scrolling="yes" frameborder="0"></iframe>Or open it as a full page / new tab:
https://bitsoffers.com/offerwall?userid=[USER_ID]&key=[API_KEY][API_KEY] with your website API key and [USER_ID] with the unique ID of the user who is viewing the wall.Parameters
| Parameter | Description | Type |
|---|---|---|
key | Your website API key. | varchar(32) |
userid | Unique identifier of the user on your site. It is returned to you in the postback. | varchar(32) |
tab (optional) | Open only one category: ptc, offers, surveys, links, faucet… | string |
Postbacks
Every time a user completes an offer we make an HTTP GET request to the Postback URL of your website with all the information you need to credit your user. Build your Postback URL with the macros below, for example:
https://yourdomain.com/postback.php?subId={{userId}}&transId={{transactionId}}&reward={{rewardValue}}¤cy={{rewardCurrency}}&payout={{payout}}&status={{status}}&userIp={{userIp}}&country={{countryCode}}&type={{type}}&signature={{secret}}Macros
| Macro | Description | Example |
|---|---|---|
{{userId}} | Unique ID of the user who completed the action. | user123 |
{{transactionId}} | Unique ID of the transaction. Use it to avoid crediting twice. | XX-12345678 |
{{rewardValue}} | Amount of your virtual currency to credit. | 1.25 |
{{rewardCurrency}} | Your currency name. | Coins |
{{payout}} | Your earnings for this lead in USD. | 0.100000 |
{{userIp}} | IP address of the user. | 192.168.1.10 |
{{countryCode}} | Country of the user (ISO-2). | US |
{{status}} | 1 = credit, 2 = chargeback (subtract the reward). | 1 |
{{type}} | Kind of lead: offers, ptc, shortlink, faucet, game, article… | offers |
{{secret}} | Signature to verify the request comes from us (see Security). | 17b4e2a7…a9f9ab |
Security
Always verify the signature. It is the MD5 of userId + transactionId + rewardValue + your SECRET KEY:
<?php
$secret = "YOUR_SECRET_KEY"; // from BitsOffers > Websites > API keys
$subId = $_GET['subId'] ?? '';
$transId = $_GET['transId'] ?? '';
$reward = $_GET['reward'] ?? '';
$signature = $_GET['signature'] ?? '';
if (md5($subId . $transId . $reward . $secret) !== $signature) {
echo "ERROR: Signature doesn't match";
exit;
}Postbacks are sent from these IP addresses. Whitelist them if your server filters requests:
Respond "ok"
Your postback must answer with the text ok. Any other answer marks the postback as failed (you can resend it later from Website Reports). We wait up to 60 seconds for your answer.
transactionId is not already in your database before crediting. If a postback is resent you will not pay twice.Full example
<?php
$secret = "YOUR_SECRET_KEY"; // from BitsOffers
// Only accept requests from BitsOffers
$allowed = ['109.123.243.168'];
$ip = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['REMOTE_ADDR'];
if (!in_array($ip, $allowed)) { echo "ERROR: Invalid source"; exit; }
$userId = $_GET['subId'] ?? null;
$transId = $_GET['transId'] ?? null;
$reward = $_GET['reward'] ?? 0;
$payout = $_GET['payout'] ?? 0;
$status = $_GET['status'] ?? 1;
$signature = $_GET['signature'] ?? null;
if (md5($userId . $transId . $reward . $secret) !== $signature) {
echo "ERROR: Signature doesn't match"; exit;
}
if ($status == 2) { // chargeback
$reward = -abs($reward);
}
if (isNewTransaction($transId)) { // your function
processTransaction($userId, $reward, $transId); // your function
}
echo "ok"; // Important!Faucet scripts
Ready-to-paste integrations for the most popular faucet scripts. Replace YOUR_SECRET_KEY and YOUR_API_KEY with the keys of your website.
VieFaucet 4.x
1. Open application/controllers/Wh.php and paste this function before the last closing bracket }:
public function bitsoffers()
{
$secret = "YOUR_SECRET_KEY"; // BitsOffers secret key
$holdDays = 1; // days on hold (0 = no hold)
$minHold = 0.1; // rewards lower than this are not held
$userId = $this->db->escape_str($_GET['subId'] ?? '');
$transactionId = $this->db->escape_str($_GET['transId'] ?? '');
$reward = $this->db->escape_str($_GET['reward'] ?? 0);
$userIp = $this->db->escape_str($_GET['userIp'] ?? '0.0.0.0');
$signature = $this->db->escape_str($_GET['signature'] ?? '');
$status = $this->db->escape_str($_GET['status'] ?? 1);
if (md5($userId . $transactionId . $reward . $secret) != $signature) {
echo "ERROR: Signature doesn't match"; return;
}
$reward = $reward * $this->data['settings']['currency_rate'];
if ($this->m_offerwall->getTransaction($transactionId, 'bitsoffers')) { echo "DUP"; return; }
if ($status == 2) {
$this->m_offerwall->reduceUserBalance($userId, abs($reward));
$this->m_offerwall->insertTransaction($userId, 'bitsoffers', $userIp, $reward, $transactionId, 1, time());
echo "ok"; return;
}
if ($reward <= $minHold || $holdDays == 0) {
$offerId = $this->m_offerwall->insertTransaction($userId, 'bitsoffers', $userIp, $reward, $transactionId, 2, time());
$this->m_offerwall->updateUserBalance($userId, $reward);
$this->m_core->addNotification($userId, currencyDisplay($reward, $this->data['settings']) . " from BitsOffers offer #" . $offerId . " was credited.", 1);
} else {
$offerId = $this->m_offerwall->insertTransaction($userId, 'bitsoffers', $userIp, $reward, $transactionId, 0, time() + $holdDays * 86400);
$this->m_core->addNotification($userId, "Your BitsOffers offer #" . $offerId . " is pending approval.", 0);
}
echo "ok";
}2. Open application/controllers/Offerwall.php and add before the last }:
public function bitsoffers()
{
$api_key = "YOUR_API_KEY";
$this->data['page'] = 'BitsOffers Offerwall';
$this->data['iframe'] = '<iframe style="width:100%;height:800px;border:0" scrolling="yes" src="https://bitsoffers.com/offerwall?userid=' . $this->data['user']['id'] . '&key=' . $api_key . '"></iframe>';
$this->data['wait'] = 3;
$this->render('offerwall', $this->data);
}3. Add the menu link in application/views/user_template/template.php:
<li><a href="<?= site_url('offerwall/bitsoffers') ?>">BitsOffers</a></li>4. In application/config/config.php add \'wh/bitsoffers\', to $config['csrf_exclude_uris'].
Postback URL to set in BitsOffers:
https://yourdomain.com/wh/bitsoffers?subId={{userId}}&transId={{transactionId}}&reward={{rewardValue}}&payout={{payout}}&status={{status}}&userIp={{userIp}}&type={{type}}&signature={{secret}}ClaimBits / CryptoFaucet
1. Create system/gateways/bitsoffers.php with:
<?php
define('BASEPATH', true);
require('../init.php');
$secret = "YOUR_SECRET_KEY"; // BitsOffers secret key
$userId = $db->EscapeString($_GET['subId'] ?? '');
$survey = $db->EscapeString($_GET['transId'] ?? '');
$reward = $db->EscapeString($_GET['reward'] ?? 0);
$payout = $db->EscapeString($_GET['payout'] ?? 0);
$userIP = $db->EscapeString($_GET['userIp'] ?? '0.0.0.0');
$country = $db->EscapeString($_GET['country'] ?? '');
if (md5($userId . $survey . $reward . $secret) != ($_GET['signature'] ?? '')) {
echo "ERROR: Signature doesn't match"; return;
}
if ($userId !== '' && $db->QueryGetNumRows("SELECT 1 FROM `completed_offers` WHERE `survey_id`='$survey' LIMIT 1") == 0) {
$user = $db->QueryFetchArray("SELECT `id` FROM `users` WHERE `id`='$userId'");
if (!empty($user['id'])) {
$tc = max(1, (int)round(0.10 * ($payout * 100)));
$db->Query("UPDATE `users` SET `ow_credits`=`ow_credits`+'$reward', `tasks_contest`=`tasks_contest`+'$tc' WHERE `id`='{$user['id']}'");
$db->Query("INSERT INTO `completed_offers` (`user_id`,`survey_id`,`user_country`,`user_ip`,`revenue`,`reward`,`method`,`timestamp`) VALUES ('{$user['id']}','$survey','$country','" . ip2long($userIP) . "','$payout','$reward','BitsOffers','" . time() . "')");
}
}
echo 'ok';2. In template/default/pages/offers.php add a new case:
case 'bitsoffers':
$title = 'BitsOffers';
$offer_wall = '<iframe src="https://bitsoffers.com/offerwall?userid=' . $data['id'] . '&key=YOUR_API_KEY" style="width:100%;height:690px;border:0;border-radius:5px;"></iframe>';
break;3. Add the button to the offerwall list:
<a href="<?php echo GenerateURL('offers&x=bitsoffers'); ?>" class="btn btn-secondary mb-1<?php echo ($method == 'bitsoffers' ? ' active' : ''); ?>">BitsOffers</a>https://yourdomain.com/system/gateways/bitsoffers.php?subId={{userId}}&transId={{transactionId}}&reward={{rewardValue}}&payout={{payout}}&status={{status}}&userIp={{userIp}}&country={{countryCode}}&signature={{secret}}AutoFaucet (NGB Solutions)
Same steps as ClaimBits. The only difference: the payout is converted with the current BTC price. Create system/gateways/bitsoffers.php:
<?php
define('BASEPATH', true);
require('../init.php');
$secret = "YOUR_SECRET_KEY"; // BitsOffers secret key
$userId = $db->EscapeString($_GET['subId'] ?? '');
$survey = $db->EscapeString($_GET['transId'] ?? '');
$reward = $db->EscapeString($_GET['reward'] ?? 0);
$payout = $db->EscapeString($_GET['payout'] ?? 0);
$userIP = $db->EscapeString($_GET['userIp'] ?? '0.0.0.0');
$country = $db->EscapeString($_GET['country'] ?? '');
if (md5($userId . $survey . $reward . $secret) != ($_GET['signature'] ?? '')) {
echo "ERROR: Signature doesn't match"; return;
}
if ($userId !== '' && $db->QueryGetNumRows("SELECT 1 FROM `completed_offers` WHERE `survey_id`='$survey' LIMIT 1") == 0) {
$user = $db->QueryFetchArray("SELECT `id` FROM `users` WHERE `id`='$userId'");
if (!empty($user['id'])) {
$price = $db->QueryFetchArray("SELECT `value` FROM `bitcoin_price` ORDER BY `time` DESC LIMIT 1");
$usd = $price['value'] * $payout;
$tc = max(1, (int)round(0.10 * $usd));
$db->Query("UPDATE `users` SET `ow_credits`=`ow_credits`+'$reward', `tasks_contest`=`tasks_contest`+'$tc' WHERE `id`='{$user['id']}'");
$db->Query("INSERT INTO `completed_offers` (`user_id`,`survey_id`,`user_country`,`user_ip`,`revenue`,`reward`,`method`,`timestamp`) VALUES ('{$user['id']}','$survey','$country','" . ip2long($userIP) . "','$usd','$reward','BitsOffers','" . time() . "')");
}
}
echo 'ok';Then add the iframe case and button exactly like in ClaimBits.
API
Show BitsOffers PTC ads, shortlinks and articles with your own design. The API returns JSON; each item includes a url to open when the user clicks.
GET https://bitsoffers.com/api?type=ptc&apiKey=YOUR_PUBLIC_KEY&userId=USER_ID&device=desktop&country=us
Secret: YOUR_PRIVATE_KEY
Accept: application/json| Parameter | Description |
|---|---|
type | ptc, shortlink or article |
apiKey | Your website API (public) key |
userId | User ID on your site |
device | desktop, mobile or tablet |
country | ISO-2 country of the user (e.g. us) |
Secret (header) | Your private key |
Errors
| Message | Meaning |
|---|---|
Invaid Api key | The apiKey does not exist. |
Website Is Pending | Your website has not been approved yet. |
Access denied | API access or this category is not enabled for your website. |
Access to this resource is denied | Missing parameters or wrong Secret header. |
PTC
<?php
function bitsoffers_api($type, $country = 'us', $userId = 1) {
$ua = strtolower($_SERVER['HTTP_USER_AGENT'] ?? '');
$device = strpos($ua, 'mobile') !== false ? 'mobile' : (strpos($ua, 'tablet') !== false ? 'tablet' : 'desktop');
$query = http_build_query([
'type' => $type, // ptc | shortlink | article
'apiKey' => 'YOUR_PUBLIC_KEY',
'userId' => $userId,
'device' => $device,
'country' => strtolower($country),
]);
$ch = curl_init('https://bitsoffers.com/api?' . $query);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_HTTPHEADER => ['Secret: YOUR_PRIVATE_KEY', 'Accept: application/json'],
]);
$res = curl_exec($ch);
curl_close($ch);
return json_decode($res, true);
}
$ptc = bitsoffers_api('ptc', 'us', $currentUserId);Response:
{
"status": "success",
"msg": "Request completed successfully",
"total_reward": "12.5",
"total_duration": 90,
"total_ads": 3,
"data": [
{ "id": 14, "name": "Visit CryptoSite", "description": "Stay 30 seconds",
"reward": "5", "timer": 30, "adtype": "surfads",
"url": "https://bitsoffers.com/offerwall/sptcview?token=...", "currency_name": "Coins" }
]
}| Field | Description |
|---|---|
reward | Reward in your currency (your exchange rate is already applied). |
timer | Seconds the user must stay on the ad. |
adtype | surfads (opens in our viewer) or windowads (opens in a new window). |
url | Open this URL when the user clicks. The reward is sent to your Postback URL with type=ptc. |
Shortlinks
Same function, just change the type:
$links = bitsoffers_api('shortlink', 'us', $currentUserId);{
"status": "success",
"msg": "Request completed successfully",
"total_reward": "20",
"available": 6,
"total_links": 3,
"data": [
{ "id": 7, "name": "EarnLinks", "reward": "4", "view_per_day": 2, "remain_views": 2,
"url": "https://bitsoffers.com/offerwall/linkgenerate?token=...", "currency_name": "Coins" }
]
}Show only links with remain_views > 0. The reward arrives in your postback with type=shortlink.
Read articles
Returns the daily article cards of the user. Each card can be completed once per day: limit: "1/1" is available and "0/1" is already used (disabled: 1).
$articles = bitsoffers_api('article', 'us', $currentUserId);{
"status": "success",
"daily_limit": 10,
"completed_today": 2,
"available": 8,
"data": [
{ "id": 3, "name": "Read Article #3", "reward": "1", "timer": 30,
"limit": "1/1", "completed": 0, "disabled": 0,
"url": "https://bitsoffers.com/offerwall/article_continue?...", "currency_name": "Coins" }
]
}