Contents
1. Authentication
Base URL:https://sladu.net
API uses Bearer tokens (Laravel Sanctum). Get a token:
POST /api/auth/token
Content-Type: application/json
{ "email": "you@example.com", "password": "your-password" }
→ 200 OK
{ "token": "1|abc...xyz", "user": { "id": 42, "role": "advertiser" } }
All subsequent requests:
Authorization: Bearer 1|abc...xyz Accept: application/json
2. Campaigns (advertiser)
Campaign list
GET /api/adv/campaigns
→ 200 OK
{
"campaigns": [
{
"id": 7, "name": "Casino RU CPM",
"vertical": "gambling", "format": "native",
"bid_type": "cpm", "bid_micro_cents": 200000,
"status": "active",
"daily_budget_cents": 5000,
"daily_spent_cents": 1234,
"created_at": "2026-06-15T12:00:00Z"
}
]
}
Create campaign
POST /api/adv/campaigns
{
"name": "Casino RU CPM",
"vertical": "gambling",
"format": "native",
"bid_type": "cpm",
"bid_usd": 2.0,
"daily_budget_usd": 50,
"geo_include": ["ru","ua","kz"],
"languages": ["ru"]
}
→ 201 Created
{ "id": 8, "name": "Casino RU CPM", "status": "draft", ... }
Activate / pause
POST /api/adv/campaigns/{id}/activate
POST /api/adv/campaigns/{id}/pause
3. Creatives
Add creative
POST /api/adv/campaigns/{campaign_id}/creatives
Content-Type: multipart/form-data
title=Получи $50 бонус
body=Регистрация за 1 минуту...
landing_url=https://your-offer.com/?sub1={click_id}
image=@banner.jpg # файл, для не-video
video_url=https://cdn.../ad.mp4 # для video / floating_video
cta_text=Зарегистрироваться
orientation=vertical # для floating_video
→ 201 Created
{
"id": 42, "status": "pending_moderation",
"tracking_token": "tt_video_xyz",
"moderation_eta_seconds": 120
}
AI headline generation (Claude)
POST /api/adv/campaigns/{id}/ai-generate
{
"offer": "Казино с бонусом 5000₽ на первый депозит",
"cta": "Зарегистрироваться",
"geo": "RU", "lang": "ru"
}
→ 200 OK
{
"variants": [
{ "title": "...", "body": "...", "hook_type": "fear" },
{ "title": "...", "body": "...", "hook_type": "curiosity" },
... (8 шт)
],
"image_prompts": [
{ "prompt": "...", "style": "photoreal" },
... (4 шт)
],
"usage": { "input_tokens": 350, "output_tokens": 1200 }
}
HeyGen AI Video
POST /api/adv/heygen/generate
{
"campaign_id": 7,
"avatar_id": "Anna_public_3_20240108",
"voice_id": "...",
"script": "Привет! 👋 Если ты ищешь...",
"language": "ru",
"orientation": "vertical"
}
→ 200 OK
{ "ok": true, "job_id": 123, "status": "processing", "cost_cents": 100 }
GET /api/adv/heygen/status/{job_id}
→ 200 OK
{ "status": "completed", "video_url": "https://...", "duration_sec": 18 }
4. Sites (publisher)
Add site
POST /api/pub/sites
{
"domain": "example.com",
"category": "adult_video", # см. /pub/sites/create - 29 категорий
"language": "ru",
"traffic_estimate_daily": 50000
}
→ 201 Created
{
"id": 42,
"domain": "example.com",
"verification_code": "SLADU-XYZ123ABC",
"status": "draft"
}
Verify ownership
POST /api/pub/sites/{id}/verify
→ 200 OK
{ "ok": true, "method": "meta", "status": "pending_review" }
# Если не нашли код - 422:
{ "ok": false, "error": "Не нашли verification code на странице..." }
5. Blocks (publisher)
Create unit
POST /api/pub/zones
{
"site_id": 42,
"name": "Главная боковая",
"format": "floating_video",
"fv_corner": "br", # br/bl/tr/tl
"fv_delay_sec": 3,
"fv_freq_cap_hours": 6,
"banner_width": 320,
"banner_height": 568
}
→ 201 Created
{
"id": 100,
"subid": "abc12345",
"widget_url": "https://sladu.net/w/abc12345.js",
"vast_url": "https://sladu.net/vast/abc12345.xml", # только для video
"status": "active"
}
6. Statistics
GET /api/adv/stats?from=2026-06-01&to=2026-06-23&group_by=day,campaign
→ 200 OK
{
"rows": [
{
"date": "2026-06-23", "campaign_id": 7,
"impressions": 12500, "clicks": 142, "ctr": 1.14,
"spent_cents": 2500, "conversions": 8,
"ecpa_cents": 312
},
...
]
}
Available groupings:day, hour, campaign, creative, geo, device, site, zone.
7. S2S postback - incoming (from your tracker to us)
When a conversion is recorded in your tracker (Voluum, BeMob, RedTrack, Keitaro) — use this URL with macros:
https://sladu.net/postback/in?secret=ABC123&click_id={click_id}&payout=500&status=approved&txid={tx_id}
Parameters:
secret- from/cabinet/profile → «Postback secret»click_id- the UUID we passed inlanding_urlvia macro{click_id}payout- conversion amount incents (500 = $5)status-approved/pending/rejectedtxid— unique transaction ID (deduplication)sig(optional, but recommended) - HMAC signature
HMAC signature (protection against forgery)
Formula:
payload = "{click_id}|{payout}|{status}|{txid}"
sig = hash_hmac('sha256', payload, secret)
Example (PHP):
$secret = 'ABC123';
$payload = $clickId . '|' . $payout . '|' . $status . '|' . $txid;
$sig = hash_hmac('sha256', $payload, $secret);
$url = "https://sladu.net/postback/in?secret={$secret}&click_id={$clickId}&payout={$payout}&status={$status}&txid={$txid}&sig={$sig}";
Without sig — we accept (backward compatibility), but log a warning. With sig — we check for an exact match.
8. S2S postback - outgoing (from us to you)
In/cabinet/profileenter a URL pattern, for example:
https://your-tracker.com/postback?cid={click_id}&payout={payout_cents}&status={status}&geo={geo}&device={device}
Available macros:
{click_id}- Click UUID{payout_cents}- conversion amount{status}- approved/pending/rejected{geo}- country ISO code{device}- desktop/mobile/tablet{os},{browser},{vertical},{campaign_id}
Postback is triggered with retry logic: up to 5 attempts with exponential backoff (5s, 30s, 5min, 30min, 2h). If all failed — the conversion is marked aspostback_failed, we keep counting in our metrics.
9. OpenRTB 2.5 (for DSP partners)
Sladu acts asSSPfor external DSPs. Every impression is an auction. If you want to connect your DSP to our impressions — here is the endpoint:
POST https://sladu.net/openrtb/bid
Content-Type: application/json
x-openrtb-version: 2.5
{
"id": "bid-request-uuid",
"imp": [{
"id": "1",
"bidfloor": 0.5,
"banner": { "w": 300, "h": 250 },
...
}],
"site": { "domain": "publisher.com", "cat": ["IAB7"] },
"device": { "ua": "...", "ip": "1.2.3.4", "geo": { "country": "RU" } },
"user": { "id": "hashed-cookie-id" }
}
← 200 OK
{
"id": "bid-request-uuid",
"seatbid": [{
"bid": [{
"id": "1",
"impid": "1",
"price": 1.5,
"adm": "...creative HTML...",
"nurl": "https://your-dsp/win-notify?...",
"crid": "creative-id"
}]
}]
}
Auction timeout is 200ms. QPS limit is individual (default 100 req/sec, increased after passing integration tests).
To connect — write todsp@sladu.net, we'll provide an IP whitelist and a test endpoint.
10. Widget endpoints (for developers)
These are the endpoints called by our JS widget on webmaster sites. You will need this if you are building a custom client:
GET /w/{subid}.js— the widget itself (JavaScript)GET /imp?z={subid}&fp={fingerprint}⊥={signals}- ad display request, returns JSON with a creativeGET /c/{impression_id}/{tracking_token}?ttc=&x=&y=&focus=&fp=⊥=- click tracking, redirect to landingGET /vast/{subid}.xml— VAST 4.0 XML for video formatPOST /push/subscribe- web-push subscriptionGET /openrtb/imptracker/{imp_id}- VAST impression pixel
11. VAST 4.0
Full VAST documentation —/docs/vast. In short: each video block has a URL likehttps://sladu.net/vast/{subid}.xml, understood by JW Player, video.js, IMA SDK and others.
12. Rate limits and errors
Rate limits
- General API:60 req/minper token
- AI creative generation:1 per 30 sec(Claude is pricey)
- HeyGen generation: 1 per 5 secper user
- OpenRTB /bid: individual, seesection 9
Exceeded - HTTP 429 + headerRetry-Afterin seconds.
Response codes
200 OK- all good201 Created— resource created400 Bad Request- validation error, in body{"errors": {...}}401 Unauthorized- token is invalid / missing402 Payment Required— funds ran out (for AI operations)403 Forbidden- no rights (third-party resource)404 Not Found- resource does not exist429 Too Many Requests- rate limit500 Internal Server Error- our error, contact support
API questions — contact us on Telegram @sladu_supportor onapi@sladu.net- Test environment / sandbox -sandbox.sladu.net (upon request).