[]{
"type": "session.close"
}{
"analysis_groups": [
"audio",
"visual"
],
"realtime_recommendation_frequency": "medium",
"realtime_recommendation_instructions": "Goal: help me close a sales call. Keep the guidance warm and concise."
}{
"transcript": [
{
"end": 2.28,
"speaker": 0,
"start": 0.44,
"text": "Yeah, yeah, exactly."
},
{
"end": 5.88,
"speaker": 0,
"start": 3,
"text": "Um I think that that makes sense."
}
],
"type": "transcript.updated"
}{
"type": "coverage.degraded",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"ranges": [
{
"start": 8,
"end": 12
}
],
"reason": "video_gap"
}
}{
"type": "coverage.dropped",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"ranges": [
{
"start": 8,
"end": 10
}
]
}
}{
"type": "error",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"code": "ih6002",
"message": "WebSocket message too large. Individual video chunks must not exceed 32 MB.",
"link": "https://docs.interhuman.ai/api-reference/error-handling#ih6002-message-too-large",
"segment": 2
}
}{
"type": "realtime_recommendation.generated",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"text": "Speaker 0 agreed but sounds unsure — invite them to name what still feels unresolved.",
"start": 0,
"end": 20
}
}{
"type": "session.closing",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"max_drain_seconds": 60
}
}{
"type": "session.ended",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"reason": "client_shutdown"
}
}{
"type": "session.ready",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"session_idle_timeout_seconds": 300,
"session_max_duration_seconds": 3600,
"min_segment_size_bytes": 1,
"max_segment_size_bytes": 33554432,
"supported_session_config_options": {
"realtime_recommendation_instructions": "string",
"realtime_recommendation_frequency": [
"high",
"medium",
"low"
],
"analysis_groups": [
"visual",
"audio"
]
}
}
}{
"type": "session.updated",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"realtime_recommendation_instructions": "Goal: help me close a sales call. Keep the guidance warm and concise.",
"realtime_recommendation_frequency": "medium",
"analysis_groups": [
"audio",
"visual"
]
}
}{
"type": "signal.detected",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"signal_type": "agreement",
"start": 3,
"probability": "high",
"modality": [
"audio",
"visual"
]
}
}{
"type": "signal.ended",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"signal_type": "agreement",
"end": 14
}
}{
"type": "signal.updated",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"signal_type": "agreement",
"start": 6,
"probability": "medium",
"modality": [
"audio",
"visual"
]
}
}Realtime Analyze
Analyze a realtime video stream.
[]{
"type": "session.close"
}{
"analysis_groups": [
"audio",
"visual"
],
"realtime_recommendation_frequency": "medium",
"realtime_recommendation_instructions": "Goal: help me close a sales call. Keep the guidance warm and concise."
}{
"transcript": [
{
"end": 2.28,
"speaker": 0,
"start": 0.44,
"text": "Yeah, yeah, exactly."
},
{
"end": 5.88,
"speaker": 0,
"start": 3,
"text": "Um I think that that makes sense."
}
],
"type": "transcript.updated"
}{
"type": "coverage.degraded",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"ranges": [
{
"start": 8,
"end": 12
}
],
"reason": "video_gap"
}
}{
"type": "coverage.dropped",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"ranges": [
{
"start": 8,
"end": 10
}
]
}
}{
"type": "error",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"code": "ih6002",
"message": "WebSocket message too large. Individual video chunks must not exceed 32 MB.",
"link": "https://docs.interhuman.ai/api-reference/error-handling#ih6002-message-too-large",
"segment": 2
}
}{
"type": "realtime_recommendation.generated",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"text": "Speaker 0 agreed but sounds unsure — invite them to name what still feels unresolved.",
"start": 0,
"end": 20
}
}{
"type": "session.closing",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"max_drain_seconds": 60
}
}{
"type": "session.ended",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"reason": "client_shutdown"
}
}{
"type": "session.ready",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"session_idle_timeout_seconds": 300,
"session_max_duration_seconds": 3600,
"min_segment_size_bytes": 1,
"max_segment_size_bytes": 33554432,
"supported_session_config_options": {
"realtime_recommendation_instructions": "string",
"realtime_recommendation_frequency": [
"high",
"medium",
"low"
],
"analysis_groups": [
"visual",
"audio"
]
}
}
}{
"type": "session.updated",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"realtime_recommendation_instructions": "Goal: help me close a sales call. Keep the guidance warm and concise.",
"realtime_recommendation_frequency": "medium",
"analysis_groups": [
"audio",
"visual"
]
}
}{
"type": "signal.detected",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"signal_type": "agreement",
"start": 3,
"probability": "high",
"modality": [
"audio",
"visual"
]
}
}{
"type": "signal.ended",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"signal_type": "agreement",
"end": 14
}
}{
"type": "signal.updated",
"timestamp": "2025-01-01T00:00:00.000000Z",
"correlation_id": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"signal_type": "agreement",
"start": 6,
"probability": "medium",
"modality": [
"audio",
"visual"
]
}
}API key authentication. Include your API key in the Authorization header as 'Bearer <api_key>'.
Optional identifier supplied by the client to correlate this request with their own logs. When provided, the value is recorded alongside the server-assigned correlation ID in Interhuman logs to aid lookup and support investigations. This header is not echoed back in the response; the server returns its own correlation ID in the X-Correlation-ID HTTP response header.
Authentication transport for clients that cannot set an Authorization header on a WebSocket connection, such as the browser WebSocket API. Send the literal subprotocol marker access_token followed by your credential, as a comma-separated subprotocol list:
Sec-WebSocket-Protocol: access_token, <credential>
In browser JavaScript, pass the same pair as the constructor's subprotocol array:
new WebSocket(url, ["access_token", credential])
access_token is the required literal marker and <credential> is your bearer credential. In a browser, this should be a short-lived access token minted server-side by the client tokens endpoint (POST /v1/client_tokens) — never your API key. The server selects and echoes access_token as the negotiated subprotocol, never the credential. Treat the credential as a secret: never log it.
access_token, <credential>Binary video segment sent by the client for analysis. Each segment must not exceed 32MB. Accepts the following formats: mp4, avi, mov, mkv, mpeg-ts, mpeg-2-ts, webm.
Inbound session.close text frame.
Caller-supplied session configuration for the realtime endpoint.
Inbound transcript.updated text frame.
Reports that one or more analysis windows were analyzed with partial visual coverage. Emitted when a window decodes materially less video than the window span while its audio runs to the end — typically a stream whose keyframe interval exceeds the analysis window (a static screen share, a long-GOP encoder). This is an informational notice, not an error: the session stays open, the windows were analyzed (audio plus whatever video decoded) and are billed normally. data.ranges lists the affected time ranges in absolute session-cumulative seconds; data.reason is currently always video_gap.
Reports that analysis coverage was reduced under backpressure. Emitted when the analysis pipeline saturates and has to skip buffered video. This is an informational notice, not an error: the session stays open, subsequent windows continue uninterrupted, and the dropped portions of the video are not billed. data.ranges lists the skipped time ranges in absolute session-cumulative seconds.
Reports an error encountered while processing the stream. data.code carries the machine-readable error id (sub-type), and data.segment identifies the incoming caller segment when the failure maps to a specific chunk (size validation, quota); analysis-time failures that do not map to one chunk carry data.segment: null.
Reports a periodic recommendation of the conversation so far. Recommendation is emitted only when all three conditions hold: the caller supplies realtime_recommendation_instructions in session.config, at least one signal has been detected, and at least one transcript has been received since the previous recommendation. Once enabled it is paced by the session-config realtime_recommendation_frequency (high/medium/low mapped to 10/20/30 seconds of analyzed video).
Acknowledges that an inbound session.close text frame was accepted. From this point the server rejects new binary video frames, finishes analyzing the video it already accepted (emitting the normal result envelopes in order), emits final lifecycle envelopes for still-open analysis state, sends session.ended, and closes the WebSocket. data.max_drain_seconds is the maximum time the caller should wait for session.ended after this acknowledgment; the session closes earlier when the accepted work finishes sooner.
The final message of a gracefully closed session. Emitted after every already-accepted analysis window has drained (or the max_drain_seconds deadline advertised on session.closing expired) and after the final lifecycle envelopes for still-open analysis state. No further analysis messages follow; the server closes the WebSocket (close code 1000) immediately after sending it.
Acknowledges that the v1 realtime session is established. Emitted exactly once per session, immediately after the server accepts the WebSocket handshake. Carries the session-level contract (idle / max-duration timeouts, segment size constraints, supported session-config options) so the caller can adapt its producer side without round-tripping rejections. supported_session_config_options advertises the values the server accepts for realtime_recommendation_instructions, realtime_recommendation_frequency, and analysis_groups.
Acknowledges that an inbound realtime_session_config_v1 text frame was accepted. Carries the consolidated post-apply realtime config (realtime_recommendation_instructions / realtime_recommendation_frequency / analysis_groups).
Reports that a social signal has transitioned from inactive to active. Emitted once when the signal type is first detected for the session, and again only when the signal becomes active after a prior signal.ended. data.start uses absolute session-cumulative time.
Reports that a previously active social signal is no longer active. Emitted when a signal type that was active in the previous analyzed window is not present in the current window. data.end uses absolute session-cumulative time.
Reports that an already-active social signal experienced a change in probability. Emitted when an active signal type's probability has changed from the previous value reported for that signal type (either signal.detected or a prior signal.updated). data.start uses absolute session-cumulative time.