Real-time
Streaming API
Get real-time progress updates during valuations. Stream events as they happen instead of waiting for the complete response.
Instant Feedback
Progress in real-time
Lower Perceived Latency
Users see activity
Partial Results
Data as available
Live Demo
Stream Simulation
Click "Start Stream" to simulate SSE events...
Event Types
start
Stream initiated
progress
Processing update
partial
Partial results
complete
Final result
error
Error occurred
heartbeat
Keep-alive ping
Implementation Examples
EventSource (Browser)
// Connect to streaming endpoint
const eventSource = new EventSource(
'https://api.justkalm.com/v2/valuate/stream?' +
new URLSearchParams({
url: 'https://example.com/product',
api_key: 'jk_live_xxx'
})
);
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Received:', data);
if (data.type === 'complete') {
eventSource.close();
console.log('Final valuation:', data.valuation);
}
};
eventSource.onerror = (error) => {
console.error('Stream error:', error);
eventSource.close();
};Fetch with ReadableStream
// Using fetch with ReadableStream
async function streamValuation(url: string) {
const response = await fetch('https://api.justkalm.com/v2/valuate/stream', {
method: 'POST',
headers: {
'Authorization': 'Bearer jk_live_xxx',
'Content-Type': 'application/json',
'Accept': 'text/event-stream',
},
body: JSON.stringify({ url }),
});
const reader = response.body?.getReader();
const decoder = new TextDecoder();
while (reader) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = JSON.parse(line.slice(6));
console.log('Event:', data);
}
}
}
}Python SDK
import httpx
from justkalm import JustKalm
client = JustKalm()
# Stream valuation with progress updates
with client.valuate_stream(url="https://example.com/product") as stream:
for evt in stream:
if evt.type == "progress":
print(f"Progress: {evt.data.progress}%")
elif evt.type == "complete":
print(f"Result: ${evt.data.price_min}-${evt.data.price_max}")Reconnection Logic
class ReconnectingEventSource {
private url: string;
private eventSource: EventSource | null = null;
private retryCount = 0;
private maxRetries = 5;
constructor(url: string) {
this.url = url;
this.connect();
}
private connect() {
this.eventSource = new EventSource(this.url);
this.eventSource.onopen = () => {
this.retryCount = 0; // Reset on successful connect
};
this.eventSource.onerror = () => {
this.eventSource?.close();
if (this.retryCount < this.maxRetries) {
const delay = Math.pow(2, this.retryCount) * 1000;
this.retryCount++;
setTimeout(() => this.connect(), delay);
}
};
}
close() {
this.eventSource?.close();
}
}Best Practices
Handle Reconnection
Implement exponential backoff for reconnection. SSE includes built-in reconnection, but customize for your needs.
Process Heartbeats
Use heartbeat events to detect stale connections. If no heartbeat for 30s, consider reconnecting.
Close When Done
Always close the EventSource when complete or on component unmount to prevent memory leaks.
Browser Limits
Browsers limit SSE connections per domain (6 in HTTP/1.1). Use HTTP/2 or multiplex connections.
Streaming vs Webhooks vs Polling
| Feature | Streaming | Webhooks | Polling |
|---|---|---|---|
| Latency | Real-time | Near real-time | Depends on interval |
| Connection | Long-lived | Push on event | Per request |
| Progress Updates | ✓ | ✗ | ✗ |
| Server Required | ✗ | ✓ | ✗ |
| Use Case | UI feedback | Async workflows | Simple checks |
Ready for Real-time?
Streaming is available on all plans. Try it in the API playground.