Summary
Overview
Generate a meeting summary from any transcript text, with the response streamed segment by segment over SSE. This endpoint is independent of the recording flow and can be used to integrate transcripts from external sources (meeting notes from other systems, pre-upload previews, and so on).
If you want to regenerate a summary for a recording that has already been uploaded to VAS, use
GET / POST /api/v1/sse/regenerate/summary/{taskId}instead.
Connection Information
| Item | Value |
|---|---|
| Endpoint | POST /api/v1/summary |
| Base Path | https://vas-poc.vurbo.ai |
| Protocol | HTTP + Server-Sent Events (SSE) response |
| Authentication | Header Authorization: Bearer <api_key> |
Note: This endpoint uses
Authorization: Bearerauthentication, which differs from theX-API-Keyused by other REST endpoints.
Request
Request Body (JSON)
| Field | Type | Required | Constraints / Default | Description |
|---|---|---|---|---|
content | string | Yes | ≤100,000 characters | Transcript content to summarize |
mode | string | Yes | enum "builtin" | "custom" | Explicit path selection |
template | string | Required for builtin / forbidden for custom | exists prompt_templates.slug | Built-in template slug |
prompt | string | Required for custom / forbidden for builtin | ≤2000 characters | The customer's full prompt (replaces the built-in prompt) |
prompt_slug | string | Required for custom / forbidden for builtin | ≤64 characters, Unicode, no control characters | The customer's own identifier (pass-through) |
format | string | No | bullet_points / paragraph / structured (default bullet_points) | Built-in output format (not applicable under custom) |
language | string | No | - | Output language code (e.g. zh-TW, en-US) |
plain_text | bool | No | Default false | Plain-text output (the backend applies Markdown post-processing to strip #/*/**/list markers, etc.) |
max_length | int | No | - | Maximum length of the summary, in words |
Mutual-exclusivity rules:
- Under
mode=builtin, you must not includepromptorprompt_slug - Under
mode=custom, you must not includetemplate, butpromptandprompt_slugare required
Violation → 400 summary_mode_field_mismatch
Request Examples
builtin mode (apply a built-in template)
curl -N -X POST "https://vas-poc.vurbo.ai/api/v1/summary" \
-H "Authorization: Bearer vas_..." \
-H "Content-Type: application/json" \
-d '{
"content": "...transcript...",
"mode": "builtin",
"template": "medical_consultation",
"language": "zh-TW",
"plain_text": true
}'
custom mode (fully customized prompt)
curl -N -X POST "https://vas-poc.vurbo.ai/api/v1/summary" \
-H "Authorization: Bearer vas_..." \
-H "Content-Type: application/json" \
-d '{
"content": "...transcript...",
"mode": "custom",
"prompt": "You are a dermatology specialist assistant. From the transcript, extract: 1) chief complaint 2) Fitzpatrick type 3) allergy history. Output JSON.",
"prompt_slug": "skin-clinic-acme-v2",
"language": "zh-TW",
"plain_text": true
}'
Effect:
- The backend does not query any built-in template
- The customer's prompt replaces the built-in template rules; only minimal default processing is applied (language, plain text, safety guard)
- The
promptcontent is forcibly snapshotted into the done event and stored in the backend record (the sole basis for reconstruction)
SSE Events
Event Sequence
1. start → Generation begins
2. chunk → Summary segment (repeated N times, includes markdown)
3. done → Generation complete (includes the final cleaned content; in custom mode, includes prompt_snapshot)
4. error → An error occurred (replaces done)
start event
{
"summary_id": "sum_abc123",
"mode": "custom",
"template": "skin-clinic-acme-v2",
"format": "bullet_points",
"language": "zh-TW",
"plain_text": true
}
| Field | Type | Description |
|---|---|---|
summary_id | string | The internal ID of this summary |
mode | string | "builtin" or "custom" |
template | string | Effective slug — builtin → the built-in slug; custom → the customer slug (i.e. the request's prompt_slug) |
format | string | Output format |
language | string | Output language |
plain_text | bool | Whether plain-text mode is enabled |
chunk event
{ "content": "This meeting discussed..." }
A streamed segment (includes markdown; the frontend can render it in real time).
done event
{
"summary_id": "sum_abc123",
"tokens_used": { "input": 1234, "output": 567 },
"created_at": "2026-05-13T08:30:00Z",
"mode": "custom",
"template": "skin-clinic-acme-v2",
"plain_text": true,
"final_content": "This meeting... (cleaned plain text when plain_text=true)",
"prompt_snapshot": "You are a dermatology specialist assistant..."
}
| Field | Type | Description |
|---|---|---|
summary_id | string | Same as in start |
tokens_used.input / .output | int | Token usage |
created_at | string | ISO 8601 timestamp |
mode | string | Same as in start |
template | string | Effective slug |
plain_text | bool | Whether plain-text mode is enabled |
final_content | string | The full content (cleaned plain text when plain_text=true) |
prompt_snapshot | string | Appears only in custom mode; the prompt content passed in verbatim by the customer (forcibly snapshotted) |
error event
{
"errorCode": "summary_mode_field_mismatch",
"message": "Field mismatch with mode",
"details": { "provider": "llm_service" }
}
Security discipline:
detailsdoes not include the LLM's internal raw error (to avoid exposing prompt fragments, API key hashes, and other sensitive information); it only indicates theprovider. The full error message goes into the server log.
Specific Error Codes
| Error Code | HTTP | Description | Recommended Action |
|---|---|---|---|
summary_text_empty | 400 | content is an empty string | Provide a valid transcript |
summary_text_too_long | 400 | content exceeds 100,000 characters | Shorten or split it |
summary_invalid_mode | 400 | mode is not builtin / custom | Change to a valid mode |
summary_mode_field_mismatch | 400 | The mode and field combination does not match (a required field is missing or a forbidden field was included) | Adjust the fields according to the mode rules |
summary_prompt_too_long | 400 | prompt exceeds 2000 characters | Shorten it |
summary_prompt_slug_too_long | 400 | prompt_slug exceeds 64 characters | Shorten it |
summary_prompt_slug_invalid | 400 | prompt_slug contains control characters (\n/\r/\t/\0, etc.) | Remove the control characters |
summary_failed | 500 | LLM generation failed | Retry later |
summary_timeout | 504 | Generation timed out | Retry later |
Integration Best Practices
- For the builtin path, first call
GET /api/v1/summary-templates/{slug}to understand the built-in template content (see summary-templates.md) - Under the custom path, your prompt must include the output language, structure description, and field requirements (the backend no longer applies built-in template rules)
- Avoid using markdown symbols in the prompt (
-,*,#) — ifplain_text=true, the backend post-processing strips them out - Do not splice untrusted end-user input directly into
prompt(you assume the prompt-injection risk; the backend includes prompt-injection protection but it is not foolproof) - Do not write passwords or API keys in
prompt(the content is sent to the LLM service for processing, and in custom mode the prompt content is stored in the backend record for auditing) - It is recommended that
prompt_sluginclude a version (e.g.acme-v1→acme-v2) so integrators can trace it - When
plain_text=true, expect fully plain-text output (even-list markers are stripped); if you need to preserve list structure, use CJK symbols (・,①②③,【】)
Related Resources
- GET /api/v1/summary-templates - Summary template list (supports
?category=) - GET /api/v1/summary-templates/{slug} - Detailed prompt for a single template
- GET / POST /api/v1/sse/regenerate/summary/{taskId} - Regenerate the summary for an existing recording
Version: V1.5.7 Last Updated: 2026-05-20