Skip to content
Documentation menu
HTTP APIMobile appsHTTP API

Mobile apps: HTTP API

Android. JSON API: session, delivery, interactions, views.

Kotlin SDK · Create a platform

Authentication

CallerAuthorizationBody
AndroidBearer <access_token>Identity from the session.
ServerBearer sk_live_…platform_id + installation_id | stable_user_id | user_id

Keep API keys server-side. Origin headers are rejected. The server key must belong to the platform owner. Use the same identity for ads, interact and seen.

POST /api/v1/mobile/session

Session
POST /api/v1/mobile/session
Content-Type: application/json
{
"platform_id": "plt_example",
"installation_id": "installation-123456789",
"os": "android",
"app_identifier": "com.example.chat"
}

Response: access_token, expires_at. Session lifetime: 1 hour. installation_id: random persistent installation ID, 16-128 characters. The package is client-provided; this is not app attestation.

Server: stable_user_id and user_id are equivalent, 1-128 characters; do not combine with installation_id. ID characters: A-Z a-z 0-9 _ . : -. os and app_identifier are required for package-restricted platforms; os must be android.

POST /api/v1/mobile/ads

Server request
POST /api/v1/mobile/ads
Authorization: Bearer sk_live_EXAMPLE
Content-Type: application/json
{
"platform_id": "plt_example",
"stable_user_id": "customer_42",
"os": "android",
"app_identifier": "com.example.chat",
"placement": "chat",
"language_code": "ru",
"context": {"question": "Headphones?", "answer": "Some options"},
"test": true,
"test_format": "card"
}
FieldValue
request_idOptional ID, 1-128 characters. Does not deduplicate server issuance.
placementchat; 1-64; A-Z a-z 0-9 _ -
language_codeen; 1-32
accept_formatstext, image, response, card, consent, quiz
contextquestion ≤4096; answer ≤16384
test / test_formatDefaults to false. test_format must be accepted. Test platforms always return demo ads.

Test returns demo ads without charges or earnings.

Response

FieldTypeValue
has_adbooleanAd availability.
adobject | nullnull on no-fill.
ad.delivery_id / ad.expires_atstringDelivery ID / ISO 8601, lifetime 7 days.
ad.formatstringtext | image | response | card | consent | quiz
ad.disclosure / ad.teststring / booleanDisclosure / test delivery.
ad.blocksarrayBlocks in display order.
ad.viewstring?Signed view receipt. Pass unchanged.

Ad blocks

typeFieldsRendering
textspans, role?Text composed of consecutive spans. role: body, brand or footer.
mediaurl, mime, alt?, role?Image or video. role=logo: logo. Appearance settings control cropping.
galleryitemsArray of media blocks. All items remain accessible.
buttonsbuttonsAll buttons and complete labels; long labels wrap.

Text span: spans[]

FieldTypeValue
textstringRequired. Plain text; line breaks preserved. No HTML.
bold / italic / underline / strikethrough / codeboolean?Span style
urlstring?HTTP(S)

Button: buttons[]

FieldTypeValue
id / textstringRequired
stylestring?primary / secondary
url / actionstringExactly one. url: navigation; action: original token for /interact.

Files and links

Media: HTTPS; image/jpeg, image/png, image/webp, image/gif, video/mp4. Video: muted, playsInline. Links: HTTP(S), no prefetch.

Example filled response
{
"has_ad": true,
"ad": {
"delivery_id": "imp_example",
"expires_at": "2099-01-01T00:00:00.000Z",
"format": "text",
"disclosure": "Sponsored",
"test": true,
"blocks": [
{
"type": "text",
"role": "body",
"spans": [
{
"text": "Try a service for your next trip.",
"bold": true
}
]
},
{
"type": "buttons",
"buttons": [
{
"id": "primary",
"text": "Learn more",
"style": "primary",
"url": "https://example.com/offer"
}
]
},
{
"type": "text",
"role": "footer",
"spans": [
{
"text": "Sponsored · Sidekick"
}
]
}
]
}
}

POST /api/v1/mobile/interact

Body (+ server identity)
{"delivery_id":"…","action":"…"}

Use the button action. Response: ok, ad. Delivery ID is preserved. Repeated actions do not bill twice. URL buttons open their url without calling interact.

POST /api/v1/mobile/seen

Body (+ server identity)
{"delivery_id":"…","view":"…"}

Send after ≥50% of the card remains visible for 1 second with an active screen and loaded media. Kotlin View/Compose handle this automatically. Custom UI requires trackView(ad) or server-side seen.

Issuance does not bill an impression. A confirmed view or interaction settles it once. Repeating seen is safe. The view receipt may expire before the ad.

Limits and errors

JSON ≤64 KiB. Sessions: 120/min per IP; operations: 120/min per platform user; issuance: 30/min. Do not automatically retry ads after an ambiguous network failure.

HTTPReason
400Invalid fields or placement.
401Invalid key or expired session.
403Origin, ownership, package, disabled platform or foreign delivery.
409View reported too early.
410Expired or invalid token.
413Body too large.
429Rate limit.
503Service unavailable.