API ReferenceDemand Source API

Demand API

Manage demand sources (DSPs), Delegate strategies, circuit breaker state, and demand-side configuration.

Base URL: https://api.praevis.com Auth: X-API-Key: {YOUR_KEY} on all requests


Demand Sources

List demand sources

GET /api/demand/sources

Query params:

ParamValuesDescription
statusactive, sandbox, archivedFilter by status
modertb, delegateFilter by integration mode

Response:

{
  "dsps": [
    {
      "id": "dsp-uuid",
      "name": "Example DSP",
      "mode": "delegate",
      "status": "active",
      "endpoint_url": null,
      "sandbox": false,
      "daily_budget_cents": 50000,
      "created_at": "2026-01-10T09:00:00Z"
    }
  ],
  "total": 3
}

Register demand source

POST /api/demand/sources

Body:

{
  "name": "My DSP",
  "mode": "rtb",
  "endpoint_url": "https://bidder.example.com/bid",
  "sandbox": false,
  "daily_budget_cents": 50000,
  "timeout_ms": 150
}
FieldRequiredDescription
name✓Display name
mode✓rtb or delegate
endpoint_urlRTB onlyBidder endpoint URL (must respond <150ms)
sandbox—Start in sandbox mode
daily_budget_cents—Daily spend cap in cents (0 = unlimited)
timeout_ms—Custom timeout override (max 150ms)

Response: 201 Created


Get demand source

GET /api/demand/sources/{id}

Update demand source

PUT /api/demand/sources/{id}

Partial update — only fields included are changed.

{
  "daily_budget_cents": 75000,
  "sandbox": false
}

Get demand source metrics

GET /api/demand/sources/{id}/stats?period=24h

Response:

{
  "dsp_id": "dsp-uuid",
  "period": "24h",
  "bid_requests": 284500,
  "bids": 97200,
  "wins": 42100,
  "impressions": 41850,
  "win_rate": 0.1480,
  "spend_cents": 61983,
  "avg_cpm_cents": 1481,
  "timeout_rate": 0.0082,
  "p50_ms": 38,
  "p95_ms": 112
}

Get demand source health

GET /api/demand/sources/{id}/health

Response:

{
  "circuit_breaker": "closed",
  "timeout_rate_5m": 0.012,
  "error_rate_5m": 0.003,
  "avg_latency_ms": 42,
  "qps_current": 87,
  "qps_limit": 200,
  "daily_budget_remaining_cents": 14230,
  "last_bid_at": "2026-02-17T14:22:01Z"
}

Circuit breaker states: closed (healthy), open (paused), half_open (recovering).


Update Delegate strategy

PUT /api/demand/sources/{id}/strategy
Content-Type: application/json

Body: Full Delegate strategy JSON

{
  "version": "1.0",
  "dsp_id": "{id}",
  "campaigns": [...],
  "rules": [...],
  "default_bid": 1.00
}

Strategy takes effect within 30 seconds across all regions.

Response: 200 OK with the saved strategy.


Reset circuit breaker

POST /api/demand/sources/{id}/reset

Manually clears an open circuit breaker. Use after fixing the underlying latency issue.

Body: Empty.

Response: 200 OK


Loss Notifications

When your bid loses an auction, Praevis fires a POST to your lurl (loss notification URL) if provided in your bid response.

How it works

Include lurl in your bid response:

{
  "id": "bid-1",
  "impid": "1",
  "price": 2.50,
  "lurl": "https://dsp.example.com/loss?auction=${AUCTION_ID}&price=${AUCTION_PRICE}&reason=${AUCTION_LOSS}"
}

Supported macros

MacroReplaced with
${AUCTION_ID}Auction request ID
${AUCTION_PRICE}Winning price (CPM)
${AUCTION_LOSS}Loss reason code

Loss reason codes (OpenRTB Table 5.25)

CodeMeaning
100Bid was below auction floor
102Lost to higher bid
{ "circuit_breaker": "closed", "message": "Circuit breaker reset successfully" }
⚠️

Resetting while the latency issue persists will retrigger the circuit breaker within seconds. Fix the endpoint first.


Pool subscriptions

List pools subscribed to

GET /api/demand/sources/{id}/pools

Response:

{
  "pools": [
    { "id": "pool-uuid", "name": "Premium CTV", "publisher_count": 8 }
  ]
}

Subscribe to pool

POST /api/demand/sources/{id}/pools/{pool_id}

Empty body. Returns 200 OK.

Unsubscribe from pool

DELETE /api/demand/sources/{id}/pools/{pool_id}

Returns 200 OK.