openapi: 3.2.0
info:
title: rtcStats rtcStats API API
version: '1.0'
description: API for third-party applications to <b>upload</b>, <b>analyze</b>, or use the <b>MCP Streamable HTTP</b> endpoint at <code>/v1.0/mcp</code>. <br/><br/>Uses Bearer token authentication. <br/><br/><b>Number formatting:</b> numeric values in responses are rounded, epoch timestamps to a whole millisecond and every other number to at most 2 decimals; integer counts and large identifiers are preserved. <br/><br/><b>Note:</b> Need to create an application token in Settings from your paid account.
servers:
- url: https://api.rtcstats.com
security:
- BearerAuth: []
tags:
- name: rtcStats API
paths:
/v1.0/upload:
post:
summary: Upload
description: 'Upload and store a WebRTC dump file or a rtcstats file to your account using a chunked flow. <br/><br/>The API works in two steps: <ul><li>- First upload chunks via multipart/form-data</li><li>- Then assemble via application/json</li></ul>The API consumes one credit if successful.'
operationId: upload
tags:
- rtcStats API
security:
- BearerAuth: []
requestBody:
content:
multipart/form-data:
schema:
type: object
required:
- chunk
- fileId
- chunkIndex
properties:
chunk:
type: string
format: binary
fileId:
type: string
description: Client-generated id for this chunked upload (same value for all chunks and assemble).
chunkIndex:
type: string
application/json:
schema:
type: object
required:
- fileId
- assemble
- fileName
properties:
fileId:
type: string
description: Same id used when uploading chunks.
assemble:
type: boolean
fileName:
type: string
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
required:
- success
properties:
success:
type: boolean
rtcstatsId:
type: string
description: Stored rtcstats session identifier. Present after assemble; absent during chunk upload. Use with GET or DELETE /sessions/{rtcstatsId}.
rtcstatsUrl:
type: string
description: Dashboard URL to open the rtcstats session. Present after assemble; absent during chunk upload.
embedUrl:
type: string
description: URL to open the session in the embedded viewer. Only present on the Enterprise plan after assemble.
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'402':
description: No credits available
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'413':
description: File exceeds size limit
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'415':
description: File rejected by the parser. <code>errorCode</code> is <code>parsing_issue</code> (corrupt or unsupported dump, generic message) or <code>other_issue</code> (invalid file or format too old, specific message)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Unexpected processing error. A generic message is returned; internal error details are not exposed
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v1.0/analyze:
post:
summary: Analyze
description: 'Upload a webrtc-internal file or a rtcstats file, process it and return summary, observations and scores. By default the session is not stored: pass query <code>save=true</code> (or <code>save=1</code>) to also persist the dump like <code>/upload</code>.<br/><br/>Send the dump the same way as <code>/upload</code>: upload the file in chunks, then send a small JSON assemble request.<br/><br/>This API consumes one credit if successful.'
operationId: analyze
tags:
- rtcStats API
security:
- BearerAuth: []
parameters:
- name: save
in: query
required: false
schema:
type: string
description: When <code>true</code> or <code>1</code>, store the file in the account in addition to returning the analysis JSON.
requestBody:
content:
application/octet-stream:
schema:
type: string
format: binary
multipart/form-data:
schema:
type: object
required:
- chunk
- fileId
- chunkIndex
properties:
chunk:
type: string
format: binary
fileId:
type: string
description: Client-generated id for this chunked upload (same value for all chunks and assemble).
chunkIndex:
type: string
application/json:
schema:
type: object
required:
- fileId
- assemble
properties:
fileId:
type: string
description: Same id used when uploading chunks.
assemble:
type: boolean
description: 'Must be <code>true</code>. Detection is shape-based: the JSON body must be at most 1KB and match this shape, otherwise it is processed as a raw JSON dump.'
fileName:
type: string
description: Optional. With <code>save=true</code>, used as the stored session's file name (extension stripped for the title) and mirrored in the response <code>data.fileName</code> / <code>data.title</code>. Ignored without save.
responses:
'200':
description: 'Success. Analysis result for a raw body or an assemble request; <code>{ success: true }</code> for a chunk request (chunk stored, nothing analyzed yet)'
content:
application/json:
schema:
oneOf:
- type: object
required:
- data
- processorVersion
properties:
data:
$ref: '#/components/schemas/AnalyzeResponseData'
rtcstatsId:
type: string
description: The rtcstats session identifier when <code>save</code> was used; otherwise absent.
rtcstatsUrl:
type: string
description: Dashboard URL to open the rtcstats session when <code>save</code> was used; otherwise absent.
processorVersion:
type: string
description: Version of the @rtcstats/rtcstats-processor package that produced the analysis (semver, e.g. 1.9.0). Resolved at response time.
embedUrl:
type: string
description: URL to open the session in the embedded viewer. Only present on the Enterprise plan when <code>save</code> was used.
- type: object
required:
- success
properties:
success:
type: boolean
description: 'Returned for multipart chunk requests: the chunk was stored, no analysis has run yet.'
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'402':
description: No credits available
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'413':
description: File exceeds size limit
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'415':
description: File rejected by the parser. <code>errorCode</code> is <code>parsing_issue</code> (corrupt or unsupported dump, generic message) or <code>other_issue</code> (invalid file or format too old, specific message)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Unexpected processing error. A generic message is returned; internal error details are not exposed
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v1.0/enrich:
post:
summary: Enrich
description: 'For a rtcstats-server or any server that only needs the observations and scores projection. Processes a webrtc-internal file or a rtcstats file and returns just that projection: experience, audio, video, connectivity and observations scores, per-severity observation counts, flat trimmed observation records, and the user-agent data. The session is never stored.<br/><br/>Send the dump the same way as <code>/upload</code>: upload the file in chunks, then send a small JSON assemble request.<br/><br/>This API consumes one credit if successful.'
operationId: enrich
tags:
- rtcStats API
security:
- BearerAuth: []
requestBody:
content:
application/octet-stream:
schema:
type: string
format: binary
multipart/form-data:
schema:
type: object
required:
- chunk
- fileId
- chunkIndex
properties:
chunk:
type: string
format: binary
fileId:
type: string
description: Client-generated id for this chunked upload (same value for all chunks and assemble).
chunkIndex:
type: string
application/json:
schema:
type: object
required:
- fileId
- assemble
properties:
fileId:
type: string
description: Same id used when uploading chunks.
assemble:
type: boolean
description: 'Must be <code>true</code>. Detection is shape-based: the JSON body must be at most 1KB and match this shape, otherwise it is processed as a raw JSON dump.'
responses:
'200':
description: 'Success. Scores and trimmed observations projection for a raw body or an assemble request; <code>{ success: true }</code> for a chunk request (chunk stored, nothing analyzed yet).'
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/EnrichResponse'
- type: object
required:
- success
properties:
success:
type: boolean
description: 'Returned for multipart chunk requests: the chunk was stored, no analysis has run yet.'
'400':
description: 'Invalid request: empty body, failed decompression, or no chunks found for the given fileId'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'402':
description: No credits available
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: API access is not included in the account plan
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'413':
description: File exceeds size limit
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'415':
description: File rejected by the parser. <code>errorCode</code> is <code>parsing_issue</code> (corrupt or unsupported dump, generic message) or <code>other_issue</code> (invalid file or format too old, specific message)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Unexpected processing error. A generic message is returned; internal error details are not exposed
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v1.0/mcp:
post:
summary: MCP Streamable HTTP
description: 'Model Context Protocol <b>Streamable HTTP</b> transport. <br/>Use an MCP client with this URL. <br/>Send <code>Authorization: Bearer</code> with your application JWT on requests that invoke tools. <br/>Exposes tools:<ul><li>- <code>get_quota</code></li><li>- <code>list_sessions</code></li><li>- <code>get_session</code></li></ul>'
operationId: mcpStreamablePost
tags:
- rtcStats API
security:
- BearerAuth: []
requestBody:
description: MCP JSON-RPC payload (when applicable).
content:
application/json:
schema:
type: object
responses:
'200':
description: Success (MCP Streamable HTTP)
headers:
Content-Type:
description: Usually `text/event-stream` for streaming responses.
schema:
type: string
example: text/event-stream
mcp-session-id:
description: Session identifier when the transport uses sessions (omitted in stateless mode).
schema:
type: string
content:
text/event-stream:
schema:
type: string
description: SSE stream. Events use `data:` lines; each payload matches **McpJsonRpcSseDataLine** (JSON-RPC 2.0 response object).
example: 'data: {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{},"serverInfo":{"name":"rtcstats","version":"1.0.0"}}}
'
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/McpStreamableHttpTransportError'
examples:
parseError:
summary: Invalid JSON or invalid JSON-RPC
value:
jsonrpc: '2.0'
error:
code: -32700
message: 'Parse error: Invalid JSON'
id: null
invalidRequest:
summary: Invalid initialization batch
value:
jsonrpc: '2.0'
error:
code: -32600
message: 'Invalid Request: Only one initialization request is allowed'
id: null
unsupportedProtocol:
summary: Unsupported MCP-Protocol-Version
value:
jsonrpc: '2.0'
error:
code: -32000
message: 'Bad Request: Unsupported protocol version: 2099-01-01 (supported versions: 2024-11-05, ...)'
id: null
'404':
description: MCP Session Not found
content:
application/json:
schema:
$ref: '#/components/schemas/McpStreamableHttpTransportError'
example:
jsonrpc: '2.0'
error:
code: -32001
message: Session not found
id: null
/v1.0/quota:
get:
summary: Quota
description: Returns total allowed credits and remaining credits for the account. Include the purchased credits.
operationId: quota
tags:
- rtcStats API
security:
- BearerAuth: []
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/QuotaResponse'
'401':
description: Missing or invalid token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v1.0/observations:
get:
summary: List observations
description: Returns the list of observations the analyzer can emit.
operationId: observations
tags:
- rtcStats API
security:
- BearerAuth: []
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/ObservationTypesResponse'
'401':
description: Missing or invalid token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: API access is not included in the account plan
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v1.0/sessions:
get:
summary: List sessions
description: Returns existing stored sessions for the token account ordered by creation date (newest first). All filters are optional. Different filters are AND-combined; multiple values within one filter are OR-combined.
operationId: listSessions
tags:
- rtcStats API
security:
- BearerAuth: []
parameters:
- name: name
in: query
required: false
description: Filter sessions whose title contains ANY of these substrings
schema:
type: array
items:
type: string
style: form
explode: true
- name: observationTypes
in: query
required: false
description: Filter sessions that contain ANY of these observation type strings (exact type name, e.g. `turnNoConfig`). Comma-separated. Only critical/high/medium observations are indexed (low/info are excluded). The full catalog of types is available from GET /v1.0/observations. Up to 20 values.
schema:
type: array
items:
type: string
style: form
explode: true
- name: observationTags
in: query
required: false
description: 'Filter sessions whose observations carry ANY of these tags. Comma-separated. Valid tags: `connectivity`, `security`, `audio`, `video`, `datachannel`, `outbound`, `inbound`, `peripheral`, `behavior`, `network`, `configuration`, `cpu`, `bug`.'
schema:
type: array
items:
type: string
style: form
explode: true
- name: os
in: query
required: false
description: 'Filter sessions by operating system (exact match). Examples: `macOS`, `Windows`, `Linux`, `Android`, `iPhone`, `iPad`.'
schema:
type: string
- name: browser
in: query
required: false
description: 'Filter sessions by browser (exact match). Examples: `Chrome`, `Safari`, `Firefox`, `Edge`.'
schema:
type: string
- name: browserVersion
in: query
required: false
description: Filter sessions by major browser version (exact match, e.g. `142`).
schema:
type: string
- name: userId
in: query
required: false
description: Filter sessions by the end-user identifier carried in the rtcstats JWT (summary metadata user).
schema:
type: string
- name: conferenceId
in: query
required: false
description: Filter sessions by the conference identifier carried in the rtcstats JWT (summary metadata conference).
schema:
type: string
- name: sessionId
in: query
required: false
description: Filter sessions by the session identifier carried in the rtcstats JWT (summary metadata session).
schema:
type: string
- name: hasCritical
in: query
required: false
description: When `true`, only sessions with at least one critical-severity observation.
schema:
type: boolean
- name: hasHigh
in: query
required: false
description: When `true`, only sessions with at least one high-severity observation.
schema:
type: boolean
- name: hasMedium
in: query
required: false
description: When `true`, only sessions with at least one medium-severity observation.
schema:
type: boolean
- name: hasLowScore
in: query
required: false
description: When `true`, only sessions whose experience score is low (`< 60`).
schema:
type: boolean
- name: hasMediumScore
in: query
required: false
description: When `true`, only sessions whose experience score is medium (`60` to `79`).
schema:
type: boolean
- name: hasHighScore
in: query
required: false
description: When `true`, only sessions whose experience score is high (`>= 80`).
schema:
type: boolean
responses:
'200':
description: Success
content:
application/json:
schema:
$ref: '#/components/schemas/SessionsListResponse'
'401':
description: Missing or invalid token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/v1.0/sessions/{rtcstatsId}:
parameters:
- name: rtcstatsId
in: path
required: true
schema:
type: string
format: uuid
description: The rtcstats session identifier
get:
summary: Retrieve Session
description: Returns the session detail including summary, observations and scores.
operationId: session
tags:
- rtcStats API
security:
- BearerAuth: []
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
required:
- data
- rtcstatsId
- rtcstatsUrl
- processorVersion
properties:
data:
$ref: '#/components/schemas/AnalyzeResponseData'
rtcstatsId:
type: string
format: uuid
description: The rtcstats session identifier
rtcstatsUrl:
type: string
description: Dashboard URL to open the rtcstats session.
processorVersion:
type: string
description: Version of the @rtcstats/rtcstats-processor package that produced the analysis (semver, e.g. 1.9.0). Resolved at response time.
embedUrl:
type: string
description: URL to open the session in the embedded viewer. Only present on the Enterprise plan.
'400':
description: Invalid session id
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Session not found for this account
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'422':
description: Reprocess failed
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
summary: Delete session
description: Deletes a stored session by its identifier.
operationId: deleteSession
tags:
- rtcStats API
security:
- BearerAuth: []
responses:
'200':
description: Success
content:
application/json:
schema:
type: object
required:
- success
properties:
success:
type: boolean
'400':
description: Invalid id
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Missing or invalid token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
Scores:
type: object
description: The five scores produced by the analyzer. Each is a number or null.
required:
- experienceScore
- audioScore
- videoScore
- connectivityScore
- observationsScore
properties:
experienceScore:
type:
- number
- 'null'
format: float
description: Overall experience score (0-100). Null when there is no media data to score against.
audioScore:
type:
- number
- 'null'
format: float
description: Audio quality score (1-5). Null when no audio stream is present.
videoScore:
type:
- number
- 'null'
format: float
description: Video quality score (1-5). Null when no video stream is present.
connectivityScore:
type:
- number
- 'null'
format: float
description: Connectivity score (1-5). Null when no peer connection produced a connectivity score.
observationsScore:
type:
- number
- 'null'
description: Aggregated severity score derived from observations. Null when unavailable.
SessionAbstract:
type: object
description: Denormalized session summary returned alongside each session in the list so clients can render badges or compute their own filters without a second call. <code>observationTypes</code> matches the <code>observationTypes</code> filter input. Every property is always present.
required:
- observationTypes
- observationTags
- browser
- browserVersion
- os
- osVersion
- conferenceId
- sessionId
- userId
- experienceScore
- connectivity
- observationsCritical
- observationsHigh
- observationsMedium
- scoreBand
properties:
observationTypes:
type: array
items:
type: string
description: Unique observation type names with severity critical/high/medium.
observationTags:
type: array
items:
type: string
description: Unique tags carried by critical/high/medium observations only.
browser:
type:
- string
- 'null'
browserVersion:
type:
- string
- 'null'
description: Major browser version only (e.g. <code>142</code>).
os:
type:
- string
- 'null'
osVersion:
type:
- string
- 'null'
conferenceId:
type:
- string
- 'null'
sessionId:
type:
- string
- 'null'
userId:
type:
- string
- 'null'
experienceScore:
type:
- number
- 'null'
connectivity:
type:
- string
- 'null'
observationsCritical:
type: integer
minimum: 0
observationsHigh:
type: integer
minimum: 0
observationsMedium:
type: integer
minimum: 0
scoreBand:
type: string
enum:
- low
- medium
- high
- unrated
description: 'Experience-score band: <code>high</code> (>= 80), <code>medium</code> (60..79), <code>low</code> (< 60), or <code>unrated</code> when there is no score.'
ObservationTypesResponse:
type: object
required:
- total
- data
properties:
total:
type: integer
description: Number of observation types in the catalog.
data:
type: array
description: Catalog of observation types, sorted by `type`.
items:
type: object
required:
- type
- title
- severity
- tags
properties:
type:
type: string
description: Unique identifier type of the observation, e.g. 'cpuPressure'.
title:
type: string
description: Human-readable title.
severity:
type: array
items:
type: string
enum:
- critical
- high
- medium
- low
- info
description: All severities this observation type can emit.
tags:
type: array
items:
type: string
enum:
- connectivity
- security
- audio
- video
- datachannel
- outbound
- inbound
- peripheral
- behavior
- network
- configuration
- cpu
- bug
description: All tags this observation type can carry.
example:
total: 2
data:
- type: cpuPressure
title: CPU pressure
severity:
- high
- medium
tags:
# --- truncated at 32 KB (52 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/rtcstats/refs/heads/main/openapi/rtcstats-rtcstats-api-api-openapi.yml