POST /ads/request
View as Markdown
Ask AI about this page
POST /api/v1/ads/requestContent-Type: application/jsonRequest
Section titled “Request”| Field | Type | Required | Notes |
|---|---|---|---|
app_key |
string | yes | Must be the app the session was issued for |
placement |
string, max 64 | yes | Placement code ([a-z0-9_]{2,64}) |
format |
banner | interstitial | rewarded |
yes | Must match the placement’s format |
session_token |
string | yes | From /sdk/initialize |
language |
string, max 35 | no | Content language such as ka or en-US (primary subtag used). Defaults to the app’s language |
android_version |
string | no | 14 or 14.0.1; the major version is used for targeting |
app_version, sdk_version |
string | no | Informational |
screen_width, screen_height |
integer 0..20000 | no | Pixels. Used to pick a banner that fits and an interstitial matching the orientation |
test_mode |
boolean | no | Serve the built-in test ad (also implied by a test session) |
test_force_no_fill |
boolean | no | Always answer no_fill with reason test_no_fill |
{"app_key":"app_xxxxxxxxxxxxxxxxxxxxxxxx","placement":"game_end","format":"interstitial", "session_token":"<opaque>","language":"ka","android_version":"14","app_version":"1.0.0", "sdk_version":"0.3.0","screen_width":1080,"screen_height":2400}Response 200: fill
Section titled “Response 200: fill”{ "status": "fill", "request_id": "req_01k9xyz...", "ad": { "id": "ad_3f2a9c01d4e5b6a7", "campaign_id": "cmp_12", "creative_id": "cr_34", "format": "interstitial", "creative_type": "image", "creative_url": "https://cdn.example.com/creatives/12/01k....png", "click_url": "https://advertiser.example", "width": 1080, "height": 1920, "duration_seconds": null, "impression_token": "<opaque>", "expires_at": "2026-10-07T18:40:00Z", "test": false }}| Field | Meaning |
|---|---|
request_id |
Send with every event for this ad |
ad.creative_type |
image (PNG, JPEG, WebP, GIF) or video (MP4, H.264) |
ad.creative_url |
Download before reporting the ad as loaded |
ad.click_url |
Advertiser landing page, opened on tap after the click event is queued |
ad.width, ad.height |
Creative size in pixels |
ad.duration_seconds |
Video length, null for images |
ad.impression_token |
Opaque, signed, single-use |
ad.expires_at |
30 minutes after the request. Never show the ad after this |
ad.test |
true for test ads (campaign_id cmp_test, creative_id cr_test_{format}) |
Response 200: no fill
Section titled “Response 200: no fill”{"status":"no_fill","request_id":"req_01k9xyz...","fallback":"admob","reason":"no_eligible_campaign"}fallback is the placement’s provider: admob or none.
| Reason | Meaning |
|---|---|
no_eligible_campaign |
No campaign matched, or none had budget left |
serving_disabled |
Global, publisher or app kill switch (or publisher/app not approved outside test mode) |
placement_disabled |
Placement paused, switched off, or disabled by an admin |
frequency_capped |
The placement’s frequency cap for this session is reached |
test_no_fill |
test_force_no_fill was set |
Selection
Section titled “Selection”- Session verified, app key matches the session, app approved (unless test).
- Placement found and format matches; kill switches; placement frequency cap.
- Test mode returns the test ad. Otherwise:
- Eligible campaigns: active, within schedule, budget left, advertiser approved with balance, country matches (or any), at least one approved creative of the requested format.
- Targeting: formats, languages, app ids, app categories, Android versions. Empty means any. A campaign that targets Android versions is skipped when the request has none.
- Campaign frequency cap for this session.
- Highest CPM bid first (ties random), with daily budget pacing.
- The cost of one impression is reserved atomically; if a campaign cannot reserve, the next one is tried.
Country comes from the network address at Qartvelo Ads’ edge, never from the device. The IP address is not stored.
Errors
Section titled “Errors”| HTTP | Code | When |
|---|---|---|
| 401 | invalid_session |
Token malformed, forged or issued for another app |
| 401 | session_expired |
Initialize again |
| 403 | app_not_approved |
App not approved and not a test session |
| 404 | placement_not_found |
No placement with that code in this app |
| 422 | format_mismatch |
format differs from the placement |
| 422 | validation_failed |
Missing or invalid fields |
| 429 | rate_limited |
See rate limits |