Skip to content

Ad Request API ​

Requests ads for a zone in real time. The endpoints are prefixed with /ad and require no authentication.

Prefer the SDK

The JS Ad SDK and the native SDKs call this API for you, including impression and click tracking. This page is for integrators who call it directly.

Before requesting, create a zone in the publisher console and get its zone_key (of the form zone_ab12cd34); see Publisher API · Zones.

Request an ad ​

GET https://aapi.adbnk.co/ad/request or POST https://aapi.adbnk.co/ad/request

Parameters can be sent as a query string, a JSON body or a form body.

ParamTypeRequiredDescription
zonestringYes*Zone code zone_key
zone_idintYes*Zone numeric ID (takes precedence if both are sent)
limitintNoNumber of ads to return, 1–5, default 1 (other values fall back to 1)
page_urlstringNoURL of the page hosting the ad
page_titlestringNoPage title
page_keywordsstringNoPage keywords
page_categorystringNoPage category
page_typestringNoPage type (article/video/product, etc.)
page_tagsstringNoPage tags, comma-separated
page_langstringNoPage language; also selects the language of the rendered html
keywordsstring / string[]NoExtra content keywords
content_urlstringNoContent URL

* One of zone or zone_id is required.

Privacy signals (all optional; send them whenever you have them):

ParamTypeDescription
gdpr0 / 1Whether GDPR applies
gdpr_consentstringIAB TCF v2 consent string
us_privacystringIAB US Privacy (CCPA) string
gpp / gpp_sidstringIAB GPP string / applicable section IDs
npa0 / 11 = non-personalized ads only
tag_for_child_directed0 / 1Child-directed treatment
tag_for_under_age0 / 1Under the age of consent

Device data is collected automatically by the ADBNK SDKs. For the best fill and measurement, integrate through an SDK.

A path form is also supported: GET / POST /ad/request/{zone_key} (the zone_ prefix may be omitted).

bash
curl "https://aapi.adbnk.co/ad/request?zone=zone_ab12cd34&limit=1&page_url=https%3A%2F%2Fblog.example.com%2Fpost%2F1"

Impressions and clicks are measured by the SDK; a request on its own is not billable.

Multiple zones in one request ​

POST a JSON body with a zones array, each entry carrying zone_key or zone_id (the other parameters above apply to all zones):

json
{ "zones": [ { "zone_key": "zone_ab12cd34" }, { "zone_id": 6 } ], "page_url": "https://blog.example.com/post/1" }

The response is data: { "batch": true, "results": [ ... ] }. Each result is a zone block shaped like a single-zone data (below), plus zone_key and zone_id. A zone that could not be served has ads: [] and an error string (zone_not_found, zone_unavailable, or another value; treat any error as a no-fill for that zone).

Response structure ​

json
{
  "code": 0,
  "message": "success",
  "data": {
    "schema_version": 2,
    "min_sdk_version": "1.0.0",
    "capabilities": ["deeplink", "mraid", "native_obj"],
    "request_id": "req_8f3a2c9d1e7b",
    "zone": {
      "id": 5,
      "code": "zone_ab12cd34",
      "width": 300,
      "height": 250,
      "type": "BANNER",
      "device": "ALL",
      "refresh": 0
    },
    "ads": [
      {
        "id": "q1w2e3r4t5y6...",
        "ad_id": 1001,
        "creative_id": 2001,
        "campaign_id": 3001,
        "zone_id": 4001,
        "type": "IMAGE",
        "title": "Summer Sale",
        "description": "Up to 50% off",
        "button_text": "Shop Now",
        "brand_name": "Example Shop",
        "image_url": "https://imgs.abnk-res.top/creatives/1.jpg",
        "image_url_2": "",
        "video_url": "",
        "icon_url": "",
        "display_url": "example.com",
        "landing_url": "https://example.com/sale",
        "click_url": "https://track.adbnk.co/track/click/q1w2e3r4t5y6...",
        "deeplink": null,
        "fallback_url": null,
        "impression_url": "https://track.adbnk.co/track/impression/q1w2e3r4t5y6...",
        "width": 300,
        "height": 250,
        "html": "<!DOCTYPE html>...<span class=\"ad-badge\">AD</span>..."
      }
    ]
  },
  "timestamp": 1752200000
}
FieldDescription
schema_versionResponse schema version (currently 2). New fields are added without bumping it — ignore fields you don't recognize.
min_sdk_versionOldest SDK version that understands this response
capabilitiesCapabilities supported by this response (deeplink, mraid, native_obj)
request_idRequest identifier; include it when contacting support
zoneZone config, see Zone object
adsAds to display; empty on a no-fill

data may contain other fields not listed here; ignore them.

No fill ​

When no ad is available, code is still 0 and data.ads is an empty array; check ads, not message. Web (non-app) requests may also get a retry hint in data.retry:

json
"retry": { "after_ms": 30000, "max": 1 }

Wait at least after_ms milliseconds before requesting again, and retry at most max times (0 = don't retry).

Errors ​

codemessage_keyMeaning
400error.ad.zone_param_missingNeither zone nor zone_id was sent
404error.ad.zone_not_foundZone does not exist
403error.ad.zone_unavailableZone is disabled or not yet approved
500error.internalServer error; try again later

Error responses have data: null. Decide success or failure from the code field in the body (0 = success). The HTTP status may be 200 even on error. message is human-readable text that may be localized; match on message_key. Treat any non-JSON or 5xx response as a temporary no-fill.

Creative structure ​

Each item in ads[] is one displayable ad. Fields without a value are null, an empty string, or omitted. An ad may carry other fields not listed here; ignore them.

FieldTypeDescription
idstringOpaque ad identifier. Don't parse it.
ad_id / creative_id / campaign_id / zone_idintNumeric IDs, for your own logging and reporting
typestringCreative type, e.g. IMAGE / NATIVE / VIDEO / RICH_MEDIA. More may be added; skip types you can't display.
title / descriptionstringHeadline / description copy
button_textstringCall-to-action text
brand_namestringBrand name
image_url / image_url_2stringImage URLs
video_urlstringVideo URL
icon_urlstringIcon URL
display_urlstringDisplay URL shown to users
landing_urlstringAdvertiser landing page, for display only. It may be null. Don't send users here directly.
click_urlstringClick URL. Open it when the user clicks; it redirects to the landing page. Use it at most once per click.
deeplinkstringApp deep link to try first (when present)
fallback_urlstringWhere to go if the deep link fails to open (only present together with deeplink)
impression_urlstringImpression tracking URL
width / heightintCreative size
htmlstringFully rendered ad HTML, ready to display in an iframe/WebView
nativeobjectStructured assets of a NATIVE ad (see below)
html_contentstringRendered template content of a RICH_MEDIA ad, for WebView display (when present)

native object: title, description, sponsor, cta_text, icon (URL), image (URL), rating (1–5), price, likes. Any of them may be null.

Clicks with a deep link: request click_url, then try deeplink. If the deep link doesn't open, go to fallback_url, else landing_url, else the page click_url redirected to.

Impression and click tracking

Use impression_url and click_url exactly as returned: don't modify, prefetch or replay them. The SDK handles impression and click measurement. See Events & Conversion Reporting.

Zone object ​

data.zone always has id, code, width, height, type, device (PC / MOBILE / ALL) and refresh (auto-refresh interval in seconds, 0 = off). Some zone types also carry display settings (trigger, frequency, close button, etc.) configured in the publisher console; the SDK applies them, so direct integrators can ignore them.

VAST video ads ​

GET https://aapi.adbnk.co/ad/render/vast/{zone_key}

Returns VAST XML for VAST-capable video players. Version 3.0 is returned by default; add vast=4 for VAST 4.2. When there is no ad, an empty <VAST> document is returned. Get the ready-to-use VAST tag for a video zone from the publisher console ("Get code"). For pre-/mid-/post-roll scheduling, copy the VMAP tag from the same place.

ParamDescription
vast4 = VAST 4.2 (default 3.0)
skip1 = make the linear ad skippable
linear / nonlinear / companion0 = leave that creative type out

Rewarded ads ​

When the user finishes a rewarded ad, the SDK notifies your page so you can grant the reward:

html
<script>
  // Either define a global handler…
  window.onAdbnkReward = function (reward) {
    // reward.zoneId, reward.userId, reward.customData, reward.rewardAmount,
    // reward.rewardType, reward.transactionId, reward.timestamp,
    // reward.signature, reward.keyId (send these to your server to check the reward)
  }
  // …or listen for the event
  document.addEventListener('adbnk:reward', function (e) { /* e.detail has the same fields */ })
</script>
  • Put data-reward-user-id (and optionally data-reward-custom-data) on the rewarded zone tag — the console's "Get code" already includes them; they are passed back to you unchanged.
  • Grant each transactionId at most once.
  • Only grant rewards for callbacks that include a transactionId.
  • Custom data can be up to 500 characters. A longer value is rejected with 400 and no reward is issued. A user id longer than 255 characters is cut to 255.

When the reward is confirmed, adbnk:reward / onAdbnkReward also carry verified: true, adId, requestId and signedFieldsComplete. All id fields (zoneId, adId, requestId, transactionId, keyId) are strings. signedFieldsComplete: false means some fields were filled in from the values sent by the page rather than returned by our server; fields with no such value (for example rewardAmount, rewardType or timestamp) may then be absent.

If the reward could not be confirmed in the browser, the SDK does not fire adbnk:reward. It fires adbnk:reward_unverified (and calls window.onAdbnkRewardUnverified if you define it) instead, with detail { zoneId, verified: false, transactionId: null, reason, timestamp, code, message, retryable } (plus requestId when known). reason is unverified or not_eligible and is kept for compatibility only; use code (see Error codes). timestamp is the browser time in milliseconds. Each shown ad fires at most one of the two events.

Neither event is proof of a reward

adbnk:reward_unverified never means a reward, and adbnk:reward is only a claim from the browser. Grant anything of value only from the server-side callback (SSV) or after checking the reward on your server (below).

Check a reward on your server ​

Before you grant anything of value, check the reward on your server. Send the transactionId, signature and keyId from the reward to your server, and call this endpoint from there:

POST https://api.adbnk.co/ad/reward/verify

This endpoint is on the platform API host api.adbnk.co, not on the ad request host used above.

ParamTypeRequiredDescription
transaction_idstringYestransactionId from the reward
signaturestringYessignature from the reward, unchanged
key_idstringNokeyId from the reward. Recommended: see the failure rules below

Request body (JSON):

json
{ "transaction_id": "rt_9f2c…", "signature": "…", "key_id": "…" }

When the reward is genuine, the response has one of two shapes. Usually the reward is found in our records and the response carries the full record:

json
{
  "code": 0,
  "data": {
    "valid": true,
    "transaction_id": "rt_9f2c…",
    "zone_id": "12345",
    "ad_id": "…",
    "request_id": "…",
    "user_id": "u123",
    "custom_data": "",
    "reward_amount": 10,
    "reward_type": "coin",
    "issued_at": "2026-10-06T08:15:30Z",
    "verified_at": "2026-10-06T08:15:31Z"
  }
}

In some cases the reward is confirmed by checking the signature instead (this needs key_id). The response then carries only valid and transaction_id:

json
{ "code": 0, "data": { "valid": true, "transaction_id": "rt_9f2c…" } }

Don't assume zone_id, user_id or the other record fields are present.

  • The fields come from our record of the reward, exactly as they were signed — not from your request. Use them, not values from the browser.
  • zone_id is the zone's numeric id, sent as a decimal string. Empty values may be returned as "" or null; treat both as empty. issued_at and verified_at are UTC, ISO 8601, ending in Z.
  • When you send key_id, a transaction that doesn't exist and a signature that doesn't match both return {"valid": false, "transaction_id": "…"}, with no other fields; the response doesn't say which check failed.
  • When you leave out key_id and the reward can't be matched, the request fails with 400 ("Missing required parameters") instead. Send key_id if you want a uniform {"valid": false} answer.
  • Check that zone_id and user_id are the ones you expect, and grant each transaction_id only once: checking the same reward again returns valid: true again.
  • A missing transaction_id or signature returns 400.

The reward the SDK receives carries the signed fields zone_id, ad_id, request_id, user_id and custom_data as they were signed, along with transaction_id, signature and key_id. Treat it as a claim until your server has checked it.

Telegram Mini App ​

Inside a Telegram Mini App, show rewarded and interstitial ads from your code:

js
window.adbnk.telegram.init({ zoneId: 'zone_xxxxxxxx', userId: 'u123' }).show()
  .then(function (result) { /* update your UI; grant rewards from the server callback */ })
  .catch(function (e) { /* e.code is a public code such as NO_FILL, USER_DISMISSED or REWARD_UNVERIFIED; e.legacyCode keeps the earlier lowercase name (no_fill, closed, skipped, busy, wrong_format, reward_failed, not_active, destroyed, error) */ })

On Telegram zones the server callback also carries tg_user_id (the Telegram user id) when it is available. It is signed like the other parameters: verify the signature over every query parameter except signature, key_id and any parameters that were already in the callback URL you configured — those are not signed. See Telegram Mini App for the full API, error codes and signature verification.

Server-side verification

Server-side signed reward callbacks (SSV) take effect once a callback URL is configured on the rewarded zone. Client-side events are not proof of a reward: adbnk:reward_unverified and the Telegram reward_failed error never mean a reward, and adbnk:reward is only a claim from the browser. Grant rewards only from the SSV callback or after a successful server-side check with POST https://api.adbnk.co/ad/reward/verify (Check a reward on your server) — with or without a callback URL.

Documentation released under the MIT License.