Skip to main content
Thrad always records user feedback internally to power ad relevancy and guarantee a consistent user experience β€” regardless of whether you opt into forwarding. If you provide a feedback_url in your creative, Thrad additionally forwards the signal to your endpoint so you can close the attribution loop in your own optimisation stack.
This is a webhook Thrad sends to you, not an endpoint you call. You implement the receiver; Thrad fires the POST.

How it works

User rates ad (πŸ‘ or πŸ‘Ž)
        ↓
Publisher SDK β†’ Thrad SSP
        ↓
Thrad records feedback internally (ad relevancy + UX guarantee)
        ↓  ← only if feedback_url was in your creative
Thrad β†’ POST {your feedback_url}  (fire-and-forget, async)

Opting in

Include feedback_url inside your creative β€” either in ad_data (pre-rendered bid) or in the render response. The URL is per-bid, so embed whatever you need to route and attribute the signal on your side. Pre-rendered bid:
{
  "data": {
    "bid": 7.50,
    "bidId": "bid_abc123",
    "ad_data": {
      "placement": "image",
      "headline": "...",
      "url": "...",
      "image_url": "...",
      "feedback_url": "https://your-dsp.com/feedback?bid=bid_abc123"
    }
  }
}
Render response (two-step flow):
{
  "data": {
    "placement": "image",
    "headline": "...",
    "url": "...",
    "image_url": "...",
    "feedback_url": "https://your-dsp.com/feedback?bid=bid_abc123"
  }
}

Request

Thrad fires a POST to your feedback_url:

Headers

HeaderValue
Content-Typeapplication/json
X-Forwarded-ForEnd-user IP from the publisher side
X-User-AgentEnd-user UA from the publisher side

Body

{
  "bid_id": "bid_abc123",
  "feedback_type": "positive",
  "feedback_text": "",
  "feedback_timestamp": "2026-05-08T15:30:00+00:00"
}
FieldTypeDescription
bid_idstringThe bidId from your bid response
feedback_type"positive" | "negative"Thumbs up or thumbs down
feedback_textstringOptional free-text comment from the user (usually empty)
feedback_timestampISO 8601When the feedback was submitted

Response

Return any 2xx within 5 seconds. Acknowledge immediately and process async:
@app.post("/feedback")
async def receive_feedback(request: Request):
    event = await request.json()
    await queue.enqueue(event)
    return {"ok": True}

Timeouts and retries

  • Thrad times out after 5 seconds.
  • No retries. If your endpoint is down the forwarded event is dropped. Thrad’s internal record is always written regardless.