Render verdicts as they land instead of waiting for the whole check. Same input as /api/check, streamed as Server-Sent Events.
The stream
POST the same body to https://fact-it-web-412159981305.us-central1.run.app/api/check/stream. The response has Content-Type: text/event-stream; each event arrives as data: <json>\n\n, where the JSON is a PipelineEvent. The terminal event is either { "type": "done", "check": Check } (carrying the full Check) or { "type": "error", ... }.
Read the body as a stream, buffer partial chunks, split on the blank-line delimiter, and JSON-parse the data: payload of each event:
const res = await fetch('https://fact-it-web-412159981305.us-central1.run.app/api/check/stream', {
method: 'POST',
headers: {
'Authorization': 'Bearer fk_your_token',
'Content-Type': 'application/json',
},
body: JSON.stringify({ response: 'The Eiffel Tower is 984 feet tall.' }),
});
if (!res.ok || !res.body) throw new Error(`stream failed: ${res.status}`);
const reader = res.body.pipeThrough(new TextDecoderStream()).getReader();
let buf = '';
while (true) {
const { value, done } = await reader.read();
if (done) break;
buf += value;
// Events are separated by a blank line; keep the trailing partial in the buffer.
const blocks = buf.split('\n\n');
buf = blocks.pop() ?? '';
for (const block of blocks) {
const line = block.split('\n').find((l) => l.startsWith('data:'));
if (!line) continue;
const event = JSON.parse(line.slice(5).trim());
switch (event.type) {
case 'extracted':
console.log('claims:', event.claims.length);
break;
case 'verdict':
console.log('verdict:', event.verdict.status);
break;
case 'done':
console.log('trust score:', event.check.overallConfidence);
break;
case 'error':
console.error('stream error:', event.message);
break;
}
}
}
This mirrors the parsing loop in @fact-it/sdk's FactItClient.stream() — inside the monorepo you can iterate that async generator directly instead of writing the reader by hand.
Next
See the full field-by-field breakdown of every event and data type in the API reference.