Fetch offers as JSON and build your own wall, when the iframe is not enough.
| Endpoint | Purpose | Credentials |
|---|---|---|
GET /api/v1/offers |
Fetch the offer feed. | apiKey + apiSecret |
GET /api/track |
Register a click and redirect to the advertiser. | apiKey, userId, offerId |
POST /api/v1/fingerprint |
Record a device fingerprint. | None |
Full reference: API Access, Parameters, Responses, Fingerprinting.
1. Your server calls GET /api/v1/offers with your
app credentials and the end user's ID
2. You render your own offer list from the returned
"data" array
3. When the user picks one, send them to the "link"
value for that offer, which carries your API key,
their user ID and the offer ID
link the API
returns for each offer. If you construct it yourself and omit the userId — or invent a
parameter name — the click fails validation, nothing is recorded, and you earn nothing with no error
shown to you.
Because your user ID is required for the click to register, a custom wall has no way to display offers anonymously. Obtain the user ID before you fetch the feed.
// Server side. Keep apiSecret out of any client-side code.
$response = Http::get('https://preads.hansaldev.com/api/v1/offers', [
'apiKey' => config('preads.api_key'),
'apiSecret' => config('preads.api_secret'),
'userId' => $request->user()->preads_id,
'limit' => 20,
]);
if ($response->successful()) {
foreach ($response->json('data') as $offer) {
// $offer['payout'] -> your earnings, USD
// $offer['payout_local'] -> what to show the user
// $offer['link'] -> where to send them
echo $offer['name'].' worth '.$offer['payout_local'].' '.$offer['currency'];
}
}
Rates apply: 60 requests per minute. Cache the response rather than fetching it on every page view.
The iframe handles these for you. With the API they become your responsibility:
country and platform and the
API filters on what your server looks like from, not what the user's browser reports —
which can differ. Pass them explicitly if you know them.
fingerprint on the tracking request if you collect
one, or you will see more false rejections than the iframe does.
If any of that is more work than you want, use the iframe.
| Symptom | Cause and fix |
|---|---|
401 INVALID_API_KEY |
Key and secret must both be correct and the app approved. Check you are not sending the publisher-level key instead of the app's. |
| Empty offer list |
Filtering came from country or platform detection. Pass country and
platform explicitly, and check meta.detected to see what the API
assumed.
|
| Users click offers and nothing converts |
The tracking request is missing userId. Use the returned link
rather than building your own.
|
422 INVALID_PARAMETERS |
Read the named fields in error.message. Common: country not two
characters, limit above 100. |
429 |
Over 60 requests per minute. Cache and back off. |
| Offer clicks are being fraud-rejected |
Add fingerprint to the tracking request. See
Fingerprinting.
|