Delegate Strategy Guide
Delegate is Praevis’s co-located bidding engine. Instead of receiving bid requests at your endpoint, your bidding logic runs inside Praevis infrastructure — evaluated in <1ms, with no network round-trip, no timeout risk, and no bidder to maintain.
Campaign API v2.0 Available: For easier campaign management, use the Campaign API instead of manually editing strategy JSON. The Campaign API provides full CRUD operations (Create, Update, Delete, Activate) with creative upload support.
| Traditional RTB | Delegate | |
|---|---|---|
| Latency | 50–150ms round-trip | <1ms (in-process) |
| Network dependency | Your datacenter | None |
| Timeout risk | Yes | None |
| Strategy format | Your code | JSON rules |
| Budget pacing | Your system | Integrated with Guide |
| Update time | Redeploy | 30 seconds |
Strategy JSON structure
{
"version": "1.0",
"dsp_id": "your-dsp-uuid",
"campaigns": [ ... ],
"rules": [ ... ],
"default_bid": 1.00
}| Field | Required | Description |
|---|---|---|
version | ✓ | Strategy format version — always "1.0" |
dsp_id | ✓ | Your demand source (DSP) UUID |
campaigns | ✓ | Array of campaign objects (budget and scheduling) |
rules | ✓ | Array of bidding rules (conditions and bid config) |
default_bid | ✓ | Fallback bid CPM if no rule matches, in USD |
Campaign object
{
"id": "campaign-001",
"name": "CTV MENA",
"active": true,
"priority": 1,
"daily_budget": 500.00,
"start_date": "2026-02-17",
"end_date": "2026-03-31"
}| Field | Required | Description |
|---|---|---|
id | ✓ | Unique campaign identifier |
name | ✓ | Display name |
active | ✓ | true / false — toggle without deleting |
priority | ✓ | Lower number = higher priority (1 wins over 2) |
daily_budget | — | Daily spend cap in cents. Even pacing reduces bid rate as budget is consumed |
total_budget | — | Total lifetime spend cap in cents |
start_date | — | ISO date — campaign starts bidding on this date |
end_date | — | ISO date — campaign stops bidding after this date |
frequency_cap | — | Object: { "max_impressions": 3, "period_hours": 24 } — limits impressions per device |
Budget Pacing
Budget enforcement runs on every bid evaluation. When daily_budget is set:
| Spend vs Budget | Bid Probability |
|---|---|
| Under 70% | 100% (bid normally) |
| 70-80% | 70% |
| 80-90% | 40% |
| 90-95% | 15% |
| 95%+ | 0% (stops bidding) |
This ensures even delivery throughout the day instead of burning budget in the first hours.
Frequency Capping
Limits how many times the same device sees a campaign’s ad within a time window. Uses device IFA (or UA+IP fingerprint) as the identifier.
{
"id": "campaign-001",
"frequency_cap": {
"max_impressions": 3,
"period_hours": 24
}
}When a device reaches max_impressions for this campaign, the campaign stops bidding for that device until the counter expires.
Rule object
{
"name": "CTV UAE Prime Time",
"campaign_id": "campaign-001",
"conditions": {
"device.devicetype": "3",
"geo.country": ["AE", "SA"],
"hour": ["18", "19", "20", "21", "22", "23"]
},
"bid": {
"base_cpm": 5.00,
"multipliers": {
"prime_time": 1.4
},
"max_cpm": 10.00,
"min_cpm": 3.00
},
"priority": 1
}| Field | Required | Description |
|---|---|---|
name | ✓ | Rule display name |
campaign_id | — | Link to a campaign (for budget tracking) |
conditions | ✓ | Conditions that must all match ({} = always match) |
bid | ✓ | Bid configuration object |
priority | ✓ | Lower = higher priority when multiple rules match |
Conditions
All conditions use AND logic — every condition must match.
| Condition key | Value type | Example |
|---|---|---|
device.devicetype | string | "3" (CTV), "1" (mobile), "2" (desktop) |
geo.country | string or array | "AE" or ["AE", "SA", "KW"] |
geo.region | string or array | "AE-DU" |
geo.city | string or array | "Dubai" |
hour | string or array | "18" or ["18","19","20"] (UTC, 0–23) |
weekday | string or array | "1" (Mon) … "6" (Sat), "0" (Sun) |
content.genre | string or array | "drama" or ["drama","thriller"] |
site.cat | string or array | "IAB1" |
publisher_id | string | Publisher-specific bidding |
deal_id | string | Private marketplace deal targeting |
All condition values must be strings, not numbers. "hour": "8" is correct; "hour": 8 will not match.
Bid configuration
| Field | Description |
|---|---|
base_cpm | Base bid in USD CPM |
multipliers | Named multipliers applied on top of base_cpm (multiplicative) |
max_cpm | Hard ceiling — bid never exceeds this |
min_cpm | Hard floor — bid never goes below this |
Effective bid = base_cpm × product(all multipliers), clamped to [min_cpm, max_cpm].
Built-in multiplier keys (applied automatically when conditions match):
| Key | When applied |
|---|---|
prime_time | Hours 18–23 UTC (if hour condition matches) |
weekend | Saturday + Sunday (if weekday condition matches) |
You can also define custom multiplier keys and apply them manually.
Example strategies
1. CTV-only, MENA geo-fenced
{
"version": "1.0",
"dsp_id": "your-dsp-uuid",
"campaigns": [
{ "id": "c1", "name": "MENA CTV", "active": true, "priority": 1, "daily_budget": 500.00 }
],
"rules": [
{
"name": "CTV MENA",
"campaign_id": "c1",
"conditions": {
"device.devicetype": "3",
"geo.country": ["AE", "SA", "KW", "QA", "BH", "OM"]
},
"bid": { "base_cpm": 6.00, "max_cpm": 12.00, "min_cpm": 3.00 },
"priority": 1
}
],
"default_bid": 0
}Setting default_bid: 0 means the demand source only bids on matched rules — no fallback bids on unmatched inventory.
2. Prime time bid multiplier
{
"version": "1.0",
"dsp_id": "your-dsp-uuid",
"campaigns": [{ "id": "c1", "name": "Prime Time", "active": true, "priority": 1 }],
"rules": [
{
"name": "Prime Time Boost",
"campaign_id": "c1",
"conditions": {
"hour": ["18", "19", "20", "21", "22", "23"]
},
"bid": {
"base_cpm": 3.00,
"multipliers": { "prime_time": 1.5 },
"max_cpm": 8.00,
"min_cpm": 1.00
},
"priority": 1
}
],
"default_bid": 2.00
}Effective bid 18–23 UTC: 3.00 × 1.5 = $4.50 CPM. Off-peak: $2.00 default.
3. Genre-targeted campaigns
{
"version": "1.0",
"dsp_id": "your-dsp-uuid",
"campaigns": [
{ "id": "drama", "name": "Drama", "active": true, "priority": 1, "daily_budget": 200.00 },
{ "id": "sport", "name": "Sport", "active": true, "priority": 2, "daily_budget": 150.00 }
],
"rules": [
{
"name": "Drama content",
"campaign_id": "drama",
"conditions": { "content.genre": "drama" },
"bid": { "base_cpm": 4.50, "max_cpm": 9.00, "min_cpm": 2.00 },
"priority": 1
},
{
"name": "Sport content",
"campaign_id": "sport",
"conditions": { "content.genre": ["sport", "sports"] },
"bid": { "base_cpm": 5.00, "max_cpm": 10.00, "min_cpm": 2.50 },
"priority": 2
}
],
"default_bid": 1.50
}4. Multi-campaign with budgets and scheduling
{
"version": "1.0",
"dsp_id": "your-dsp-uuid",
"campaigns": [
{ "id": "q1", "name": "Q1 Brand", "active": true, "priority": 1, "daily_budget": 1000.00, "start_date": "2026-01-01", "end_date": "2026-03-31" },
{ "id": "always", "name": "Always On", "active": true, "priority": 99 }
],
"rules": [
{
"name": "Q1 Premium",
"campaign_id": "q1",
"conditions": { "device.devicetype": "3" },
"bid": { "base_cpm": 7.00, "max_cpm": 15.00, "min_cpm": 4.00 },
"priority": 1
},
{
"name": "Always On Fallback",
"campaign_id": "always",
"conditions": {},
"bid": { "base_cpm": 1.50, "max_cpm": 3.00, "min_cpm": 0.50 },
"priority": 99
}
],
"default_bid": 0.50
}5. Publisher-specific deal
{
"version": "1.0",
"dsp_id": "your-dsp-uuid",
"campaigns": [{ "id": "deal", "name": "Premium Publisher Deal", "active": true, "priority": 1 }],
"rules": [
{
"name": "Publisher Direct",
"campaign_id": "deal",
"conditions": { "publisher_id": "pub-specific-uuid" },
"bid": { "base_cpm": 10.00, "max_cpm": 20.00, "min_cpm": 8.00 },
"priority": 1
}
],
"default_bid": 1.00
}Updating your strategy
Dashboard: Demand → your demand source → Strategy tab → edit JSON → Save. Takes effect within 30 seconds.
API:
PUT /api/demand/sources/{DSP_ID}/strategy
Content-Type: application/json
X-API-Key: {YOUR_KEY}
{ ...strategy JSON... }Testing before going live
- Go to Demand → your demand source → Test in Sandbox
- Adjust the test auction parameters (geo, device type, genre, hour)
- Verify your rules match and the expected bid is returned
- Check that
daily_budgetpacing works by setting a small budget and firing many test requests