JK
JustKalm
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

FeatureStreamingWebhooksPolling
LatencyReal-timeNear real-timeDepends on interval
ConnectionLong-livedPush on eventPer request
Progress Updates
Server Required
Use CaseUI feedbackAsync workflowsSimple checks

Ready for Real-time?

Streaming is available on all plans. Try it in the API playground.

© 2025 JustKalm. Stream everything.