Mobile apps: HTTP API
Android. JSON API: session, delivery, interactions, views.
Kotlin SDK · Create a platform
Authentication
| Caller | Authorization | Body |
|---|---|---|
| Android | Bearer <access_token> | Identity from the session. |
| Server | Bearer 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
POST /api/v1/mobile/sessionContent-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
POST /api/v1/mobile/adsAuthorization: Bearer sk_live_EXAMPLEContent-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"}
| Field | Value |
|---|---|
| request_id | Optional ID, 1-128 characters. Does not deduplicate server issuance. |
| placement | chat; 1-64; A-Z a-z 0-9 _ - |
| language_code | en; 1-32 |
| accept_formats | text, image, response, card, consent, quiz |
| context | question ≤4096; answer ≤16384 |
| test / test_format | Defaults to false. test_format must be accepted. Test platforms always return demo ads. |
Test returns demo ads without charges or earnings.
Response
| Field | Type | Value |
|---|---|---|
| has_ad | boolean | Ad availability. |
| ad | object | null | null on no-fill. |
| ad.delivery_id / ad.expires_at | string | Delivery ID / ISO 8601, lifetime 7 days. |
| ad.format | string | text | image | response | card | consent | quiz |
| ad.disclosure / ad.test | string / boolean | Disclosure / test delivery. |
| ad.blocks | array | Blocks in display order. |
| ad.view | string? | Signed view receipt. Pass unchanged. |
Ad blocks
| type | Fields | Rendering |
|---|---|---|
text | spans, role? | Text composed of consecutive spans. role: body, brand or footer. |
media | url, mime, alt?, role? | Image or video. role=logo: logo. Appearance settings control cropping. |
gallery | items | Array of media blocks. All items remain accessible. |
buttons | buttons | All buttons and complete labels; long labels wrap. |
Text span: spans[]
| Field | Type | Value |
|---|---|---|
text | string | Required. Plain text; line breaks preserved. No HTML. |
| bold / italic / underline / strikethrough / code | boolean? | Span style |
url | string? | HTTP(S) |
Button: buttons[]
| Field | Type | Value |
|---|---|---|
| id / text | string | Required |
style | string? | primary / secondary |
| url / action | string | Exactly 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.
{"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
{"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
{"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.
| HTTP | Reason |
|---|---|
| 400 | Invalid fields or placement. |
| 401 | Invalid key or expired session. |
| 403 | Origin, ownership, package, disabled platform or foreign delivery. |
| 409 | View reported too early. |
| 410 | Expired or invalid token. |
| 413 | Body too large. |
| 429 | Rate limit. |
| 503 | Service unavailable. |