Streaming summaries

View as Markdown

Streaming summaries combine file transcription and summarization in a multipart HTTP request. The response contains Server-Sent Events (SSE), including the completed transcript and summary text as it is generated.

Submit a recording

Use this endpoint:

POST /aiservices/speech-summarization/summarize

Authenticate with your Zoom AI Services credentials. The examples on this page send a token in the Authorization: Bearer header.

Form fieldRequiredDescription
fileYesOne audio or video file uploaded as binary data.
configNoJSON string containing transcribe and summary settings. Send it before file.

This example uploads a project-update recording and selects the corresponding static summary template:

curl --no-buffer --fail-with-body \
  https://api.zoom.us/v2/aiservices/speech-summarization/summarize \
  -H "Authorization: Bearer $TOKEN" \
  -H "Accept: text/event-stream" \
  -F 'config={"transcribe":{"language":"en-US","diarization":false,"profanity_filter":false},"summary":{"language":"en-US","template_id":"project_update","enable_dynamic_template":false,"citations":true,"should_remove_sentiment":false}}' \
  -F 'file=@project-update.wav;type=audio/wav'

Add the config part before the file part.

Let your HTTP client set the multipart Content-Type header and boundary. In cURL, -F does this automatically. --no-buffer displays events as they arrive.

Keep credentials on a trusted backend. Read the POST response as a stream with your HTTP client; a browser's native EventSource cannot submit this multipart POST request.

Configure transcription

Put recognition settings in config.transcribe. The recognition model is selected automatically and can't be changed.

FieldTypeDefaultDescription
languagestringen-USInput speech locale. Supports the ten languages listed under Multilingual model languages.
diarizationbooleanfalseIdentify different speakers in the recording.
profanity_filterbooleanfalseFilter profanity in the transcript.

For accepted media formats and upload limits, see Recording requirements.

Configure summarization

Put summary settings in config.summary. The summary language can differ from the transcription language.

FieldTypeDefaultDescription
languagestringen-USSummary output language.
template_idstringNonePredefined summary template. See Static templates.
custom_templatestringNoneA Markdown template. The summary follows its headings, structure, and formatting.
summary_lengthstringshortshort or long.
citationsbooleantrueInclude references to transcript evidence in the summary.
should_remove_sentimentbooleanfalseRemove most sentiment and emotion expressions from the summary. Removal isn't guaranteed to be complete.
enable_dynamic_templatebooleantrueAutomatically select a template based on the meeting type when no static or custom template is specified.

Automatic template

Omit template_id and custom_template and set enable_dynamic_template to true, or leave it at its default. The API detects the meeting type and selects a template.

{
    "summary": {
        "language": "en-US",
        "enable_dynamic_template": true,
        "citations": true
    }
}

Static templates

Set template_id to one of these values. Selecting a static template disables automatic template selection. You can also set enable_dynamic_template to false explicitly.

Template IDPurpose
one_on_oneOne-on-one meeting
stand_upStand-up meeting
brainstormBrainstorming session
project_updateProject update
discussionGeneral discussion
q_aQuestion-and-answer session
customer_successCustomer success call
user_feedbackUser feedback session
lecture_summaryLecture summary
next_stepsNext steps and action items

Custom template

Set custom_template to a Markdown template. The summary follows the template's headings, structure, and formatting. A custom template overrides automatic template selection. Choose one template mode per request.

{
    "summary": {
        "language": "en-US",
        "custom_template": "## Decisions\n- \n\n## Owners\n| Person | Task |\n| --- | --- |\n",
        "enable_dynamic_template": false,
        "citations": false
    }
}

Handle the event stream

A successful streaming response uses Content-Type: text/event-stream. Each event has an event: name and JSON in its data: field. A blank line separates events.

HTTP response chunks do not necessarily align with SSE event boundaries. Buffer incomplete events before parsing their JSON.

EventMeaningClient action
transcribe_startedTranscription has started.Show transcription progress.
transcribe_completeThe complete transcript is available.Save transcript for display or downstream use.
summary_updatedThe summary has been updated.Replace the displayed summary with summary_result. Check response_state.
doneProcessing completed.Save the last summary and mark the request complete.
errorA processing stage failed.Handle the error and retain any completed transcript.

Transcription events

event: transcribe_started
data: {"status":"transcribing"}

event: transcribe_complete
data: {"transcript":{"request_id":"3f2b8c1e-7a4d-4e9b-b6f0-1c5d8a2e9b47","duration_sec":5.2,"result":{"text_display":"We agreed to release the documentation on October fifteenth.","segments":[{"id":"utt_0000","start":0.0,"end":5.2,"channel":0,"speaker":"","text":"We agreed to release the documentation on October fifteenth.","words":[]}]}},"latency_ms":5234,"body_bytes":12456,"status_code":200}

transcribe_complete includes the transcription result in transcript, the transcription latency in latency_ms, the size of the transcription result in body_bytes, and the transcription status in status_code. The example shows a shortened transcript; it is not a complete list of response fields.

Summary updates

Each summary_updated event contains the full summary so far in summary_result. Replace the displayed text with each update. response_state is working during generation and completed in the final update.

Skip empty summary_result values when updating the display. HTML in the summary is escaped: <br> arrives as &lt;br&gt;.

event: summary_updated
data: {"summary_result":"## Decisions\n- Release the documentation on October fifteenth.","citations":null,"response_state":"working","error":null}

event: summary_updated
data: {"summary_result":"## Decisions\n- Release the documentation on October fifteenth.[^1]","response_state":"completed","error":null,"citations":[{"id":1,"marker":"[^1]","start_time":"00:00:00.000","end_time":"00:00:05.200","start_item_index":0,"end_item_index":0}]}

The summary is Markdown. When citations is enabled, the final update adds Markdown footnote markers, such as [^1], and a citations array that links each marker to the transcript. Earlier updates have "citations": null.

FieldDescription
idCitation number.
markerThe marker used in the summary text, such as [^1].
chunk_idID of the transcript chunk that supports the statement.
speakerSpeaker label of the cited chunk.
start_time, end_timeThe cited span of the recording, in HH:MM:SS.mmm format. Use them to find the matching transcript segments.
start_item_index, end_item_indexThe first and last transcript segments in the cited span.

Preserve the markers when displaying or storing the summary.

Completion

event: done
data: {"status":"complete","total_latency_ms":8500,"transcribe_ms":5234,"summary_ms":3266}

The done event reports total processing latency and the transcription and summary stage latencies, in milliseconds. Save the last summary_result; the done payload does not repeat the summary text.

Handle errors

Check the HTTP status, then read the SSE events. HTTP 200 starts the stream. A successful request ends with a summary_updated event with response_state: "completed", followed by done.

Treat an error event, a summary_updated event with response_state: "error", or a connection that ends before done as a failure. When processing fails, the API sends an error event without done.

HTTP statusMeaning
200Streaming response. Read events to determine the outcome.
400Invalid configuration, missing file, or unsupported format.
401 / 403Invalid credentials, or the request isn't authorized.
402Your credit is exhausted, or the credential's credit limit was reached.
405Incorrect HTTP method; use POST.
413Upload exceeds 50 MB.
429Too many requests. See rate limits.
502Transcription or summary service error.
503The summary service is temporarily unavailable.

An SSE error identifies the failed stage:

event: error
data: {"error":"transcribe failed: connection timeout","stage":"transcribe"}

StageMeaning
transcribeTranscription failed.
summary_preparationPreparing the transcript for summarization failed.
summarySummary generation failed.

If transcription fails, the API does not return a partial transcript. If summary generation fails after transcribe_complete, retain the completed transcript and show that summarization did not finish.