Streaming results
Results arrive over Server-Sent Events as research finishes, rather than you polling for them.
Connect
Server-side, with a header:
curl -N "$RTFC/stream?debate_id=$DEBATE" -H "X-Auth-Token: $TOKEN"From a browser - EventSource cannot send headers, so mint a short-lived stream token server-side and pass it in the query string:
curl -sX POST $RTFC/stream/token -H "X-Auth-Token: $TOKEN"
# {"stream_token": "…"}const es = new EventSource(`${RTFC}/stream?token=${streamToken}&debate_id=${debateId}`);A stream token lasts 5 minutes and works only for the stream endpoints - it is rejected as a general bearer token, so putting it in a URL risks far less than a PAT would.
The event contract
Events are JSON on the data: line. RTFC never sets the SSE event: field - switch on the type property in the payload:
data: {"type":"ping"}
data: {"type":"new_claim","claim_id":"…","claim_text":"…","debate_id":"…"}
data: {"type":"result","claim_id":"…","query_id":"…","verdict":"false","confidence":0.97, …}type | Meaning |
|---|---|
ping | Keepalive, every 20s. Ignore it. |
new_claim | A claim was detected. Show a pending card. |
result | A panel finished. |
claim_complete | Every expected method finished for a claim; carries the best answer. |
Ignore any type you do not recognise - new ones may appear.
A result event carries cost_usd for that panel and claim_total_cost_usd for the claim so far, so you can meter without a second request.
Per-claim progress
GET /v1/stream/claim/{claim_id} streams one claim's research progress - search steps, documents fetched - and closes on the verdict. Useful for a detail view where showing work reduces perceived latency.
Reconnecting
The connection can drop; treat that as normal. EventSource reconnects on its own, but your token may have expired - mint a new one and reopen. Nothing is lost: GET /v1/claims/{id}/results always has the current state, so reconcile on reconnect rather than assuming you saw every event.
If holding a connection is awkward - a mobile app that gets backgrounded, a serverless backend - use webhooks instead.