Retranslate
Connection Information
| Item | Value |
|---|---|
| Base path | https://vas-poc.vurbo.ai/api/v1/sse |
| Protocol | HTTP + Server-Sent Events (SSE) |
| Data format | text/event-stream |
| Authentication | Header X-API-Key: {KEY} |
Note: The browser's native EventSource API does not support custom headers. Use the fetch API together with ReadableStream, or use an SSE client library that supports headers.
Endpoint Overview
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/sse/retranslate/{taskId} | Retranslate full transcript |
| GET | /api/v1/sse/retranslate/summary/{taskId} | Retranslate summary |
| GET | /api/v1/sse/recordings/{taskId}/entries/{sid}/retranslate | Retranslate a single sentence (use after editing the original text) |
GET /api/v1/sse/retranslate/{taskId}
Description
Retranslates all sentences of the specified task into the target language. Translation results are streamed one by one over SSE.
Use Cases
- Switching the display language
- Updating translated content
Authentication
Header: X-API-Key (see Authentication)
Request Parameters
| Parameter | Location | Type | Required | Description |
|---|---|---|---|---|
taskId | path | string | Yes | Recording ID (UUID) |
targetLang | query | string | Yes | Target language code (e.g., en-US) |
Request Example
curl -N "https://vas-poc.vurbo.ai/api/v1/sse/retranslate/550e8400-e29b-41d4-a716-446655440000?targetLang=en-US" \
-H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW"
// Use the fetch API (because EventSource does not support headers)
async function retranslateSSE(taskId, targetLang, apiKey) {
const response = await fetch(
`https://vas-poc.vurbo.ai/api/v1/sse/retranslate/${taskId}?targetLang=${targetLang}`,
{
headers: {
'X-API-Key': apiKey
}
}
);
const reader = response.body.getReader();
// ... handle SSE events
}
Event Sequence
1. translation → sends translation results one by one (successful sentences, repeated N times)
error → a sentence failed to translate (per-sid, interleaved with translation)
2. done → translation complete
Failed sentences do not emit
translation; instead they emitevent: errorcarryingsid+error_code. The frontend can handle these with the sametranslationError.tsinterceptor (aligned with the WebSocket spec).
Event Format
translation
{
"sid": 1,
"text": "Hello",
"is_final": true
}
| Field | Type | Description |
|---|---|---|
sid | number | Sentence ID |
text | string | Translation result |
is_final | boolean | Whether this is the final result |
error (per-sid failure)
When a sentence fails to translate (e.g., content filtering, provider error), translation is not emitted; error is emitted instead:
{
"error_code": "sse_translation_failed",
"severity": "error",
"message": "SSE translation failed",
"context": "sse",
"sid": 5,
"request_id": "req_abc123",
"timestamp": "2026-04-26T10:30:45.123Z",
"details": {
"translation_language": "ja",
"original_error": "..."
}
}
| Field | Type | Description |
|---|---|---|
error_code | string | Error code, commonly sse_translation_failed |
severity | string | Severity |
message | string | Human-readable message |
context | string | Error context (translation) |
sid | int | Number of the failed sentence |
details | object | Debug information including translation_language, original_error, etc. |
Failed sentences are stored as translation error records (see history-playback), so the failure markers appear the next time the history is loaded.
done
{
"totalUpdated": 10
}
| Field | Type | Description |
|---|---|---|
totalUpdated | number | Total number of sentences updated (excluding failed sentences) |
Specific Error Codes
| Error Code | HTTP Status | Description | Recommended Action |
|---|---|---|---|
sse_missing_target_lang | 422 | Missing target language parameter | Provide the targetLang parameter |
sse_unsupported_language | 422 | Unsupported target language | Use a valid language code |
sse_translation_failed | 500 | Translation failed (per-sid) | The failed sentence is still reported via event: error; the overall flow is not interrupted |
Frontend Example
async function retranslate(taskId, targetLang, apiKey) {
const response = await fetch(
`https://vas-poc.vurbo.ai/api/v1/sse/retranslate/${taskId}?targetLang=${targetLang}`,
{
headers: {
'X-API-Key': apiKey
}
}
);
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const events = parseSSE(decoder.decode(value));
for (const event of events) {
if (event.type === 'translation') {
console.log(`Sentence ${event.data.sid}: ${event.data.text}`);
} else if (event.type === 'done') {
console.log(`Done, ${event.data.totalUpdated} sentences updated`);
}
}
}
}
GET /api/v1/sse/retranslate/summary/{taskId}
Description
Retranslates the summary of the specified task into the target language. Translation results are streamed segment by segment over SSE.
Use Cases
- Switching the summary display language
- Obtaining the summary in a different language
Authentication
Header: X-API-Key (see Authentication)
Request Parameters
| Parameter | Location | Type | Required | Description |
|---|---|---|---|---|
taskId | path | string | Yes | Recording ID (UUID) |
targetLang | query | string | Yes | Target language code (e.g., en-US) |
Request Example
curl -N "https://vas-poc.vurbo.ai/api/v1/sse/retranslate/summary/550e8400-e29b-41d4-a716-446655440000?targetLang=en-US" \
-H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW"
// Use the fetch API (because EventSource does not support headers)
async function retranslateSummarySSE(taskId, targetLang, apiKey) {
const response = await fetch(
`https://vas-poc.vurbo.ai/api/v1/sse/retranslate/summary/${taskId}?targetLang=${targetLang}`,
{
headers: {
'X-API-Key': apiKey
}
}
);
const reader = response.body.getReader();
// ... handle SSE events
}
Event Sequence
1. summary_translation → sends summary translation segment by segment (repeated N times)
2. done → translation complete
Event Format
summary_translation
{
"text": "Accumulated translation result...",
"is_final": false
}
| Field | Type | Description |
|---|---|---|
text | string | Accumulated translation result (streamed, grows gradually) |
is_final | boolean | Whether this is the final result (the last item is true) |
done
{
"totalUpdated": 1
}
| Field | Type | Description |
|---|---|---|
totalUpdated | number | Number of summaries updated (always 1) |
Specific Error Codes
| Error Code | HTTP Status | Description | Recommended Action |
|---|---|---|---|
sse_summary_not_found | 404 | Summary not found | This recording has no summary |
sse_summary_translation_failed | 500 | Summary translation failed | Try again later |
GET /api/v1/sse/recordings/{taskId}/entries/{sid}/retranslate
Description
Retranslates a single sentence. The most common scenario: after a user edits the original text via PATCH /api/v1/recordings/{id}/entries/{sid}, this endpoint is called to redo all translations of that sentence.
Differences from full-transcript retranslation (/retranslate/{taskId}):
- Full-transcript retranslation: translates all sentences into a specified language (a single target language)
- Single-sentence retranslation: translates only one sentence, but can translate into all existing target languages at once
Use Cases
- Automatically triggered after a user edits the STT original text
- Recovery for individual sentences that failed to translate
Authentication
Query: api_key (an SSE endpoint limitation, since the browser's EventSource cannot send headers). See Authentication.
Request Parameters
| Parameter | Location | Type | Required | Description |
|---|---|---|---|---|
taskId | path | string | Yes | Recording ID (UUID) |
sid | path | number | Yes | Sentence ID (1-based) |
targetLang | query | string | No | Target language code. When omitted, all languages already present in translated_texts for that sentence are retranslated |
expectedRevision | query | number | No | Optimistic lock: the current transcript revision; a mismatch returns transcript_revision_conflict |
api_key | query | string | Yes | API Key |
Request Example
# Retranslate all existing languages
curl -N "https://vas-poc.vurbo.ai/api/v1/sse/recordings/{taskId}/entries/5/retranslate?api_key=vas_xxx"
# Retranslate only en-US, and require the revision to be 3
curl -N "https://vas-poc.vurbo.ai/api/v1/sse/recordings/{taskId}/entries/5/retranslate?targetLang=en-US&expectedRevision=3&api_key=vas_xxx"
Event Sequence
1. connected → connection confirmed
2. progress → started translating a language (once per language)
3. translated → that language's translation completed (once per language)
or error → that language's translation failed
4. done → all complete
Event Format
progress
{ "sid": 5, "lang": "en-US", "status": "translating" }
translated
{
"sid": 5,
"lang": "en-US",
"text": "Hello world",
"tokens_used": 25
}
error (single-language failure)
{
"error_code": "sse_translation_failed",
"sid": 5,
"details": { "translation_language": "ja-JP", "original_error": "..." }
}
done
{
"sid": 5,
"revision": 6,
"original_text_edited_at": "2026-05-06T10:30:00.000000Z",
"languages_translated": ["en-US"],
"languages_failed": ["ja-JP"]
}
| Field | Type | Description |
|---|---|---|
sid | number | Sentence ID |
revision | number | The new revision after the write (used for the next optimistic lock) |
original_text_edited_at | string|null | Time the original text was edited (if this sentence has been edited) |
languages_translated | array | Language codes that were translated successfully |
languages_failed | array | Language codes that failed to translate |
Specific Error Codes
| Error Code | HTTP Status | Description | Recommended Action |
|---|---|---|---|
recording_not_found | 404 | Recording does not exist or does not belong to this user | Verify that taskId is correct |
recording_not_completed | 422 | Recording processing is not yet complete | Wait for the recording to complete, then try again |
entry_not_found | 404 | The specified sentence was not found | Verify that sid is correct |
entry_text_empty | 422 | The original text of this sentence is empty | Edit the original text via PATCH first |
transcript_revision_conflict | 409 | Revision mismatch (modified by another request) | Reload the transcript to get the latest revision, then try again |
storage_upload_failed | 500 | Failed to save the transcript | Try again later |
Version: V1.5.7 Last Updated: 2026-05-20