SSE API

Retranslate

Connection Information

ItemValue
Base pathhttps://vas-poc.vurbo.ai/api/v1/sse
ProtocolHTTP + Server-Sent Events (SSE)
Data formattext/event-stream
AuthenticationHeader 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

MethodEndpointDescription
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}/retranslateRetranslate 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

ParameterLocationTypeRequiredDescription
taskIdpathstringYesRecording ID (UUID)
targetLangquerystringYesTarget 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 emit event: error carrying sid + error_code. The frontend can handle these with the same translationError.ts interceptor (aligned with the WebSocket spec).

Event Format


translation

{
  "sid": 1,
  "text": "Hello",
  "is_final": true
}
FieldTypeDescription
sidnumberSentence ID
textstringTranslation result
is_finalbooleanWhether 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": "..."
  }
}
FieldTypeDescription
error_codestringError code, commonly sse_translation_failed
severitystringSeverity
messagestringHuman-readable message
contextstringError context (translation)
sidintNumber of the failed sentence
detailsobjectDebug 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
}
FieldTypeDescription
totalUpdatednumberTotal number of sentences updated (excluding failed sentences)

Specific Error Codes

Error CodeHTTP StatusDescriptionRecommended Action
sse_missing_target_lang422Missing target language parameterProvide the targetLang parameter
sse_unsupported_language422Unsupported target languageUse a valid language code
sse_translation_failed500Translation 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

ParameterLocationTypeRequiredDescription
taskIdpathstringYesRecording ID (UUID)
targetLangquerystringYesTarget 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
}
FieldTypeDescription
textstringAccumulated translation result (streamed, grows gradually)
is_finalbooleanWhether this is the final result (the last item is true)

done

{
  "totalUpdated": 1
}
FieldTypeDescription
totalUpdatednumberNumber of summaries updated (always 1)

Specific Error Codes

Error CodeHTTP StatusDescriptionRecommended Action
sse_summary_not_found404Summary not foundThis recording has no summary
sse_summary_translation_failed500Summary translation failedTry 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

ParameterLocationTypeRequiredDescription
taskIdpathstringYesRecording ID (UUID)
sidpathnumberYesSentence ID (1-based)
targetLangquerystringNoTarget language code. When omitted, all languages already present in translated_texts for that sentence are retranslated
expectedRevisionquerynumberNoOptimistic lock: the current transcript revision; a mismatch returns transcript_revision_conflict
api_keyquerystringYesAPI 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"]
}
FieldTypeDescription
sidnumberSentence ID
revisionnumberThe new revision after the write (used for the next optimistic lock)
original_text_edited_atstring|nullTime the original text was edited (if this sentence has been edited)
languages_translatedarrayLanguage codes that were translated successfully
languages_failedarrayLanguage codes that failed to translate

Specific Error Codes

Error CodeHTTP StatusDescriptionRecommended Action
recording_not_found404Recording does not exist or does not belong to this userVerify that taskId is correct
recording_not_completed422Recording processing is not yet completeWait for the recording to complete, then try again
entry_not_found404The specified sentence was not foundVerify that sid is correct
entry_text_empty422The original text of this sentence is emptyEdit the original text via PATCH first
transcript_revision_conflict409Revision mismatch (modified by another request)Reload the transcript to get the latest revision, then try again
storage_upload_failed500Failed to save the transcriptTry again later

Version: V1.5.7 Last Updated: 2026-05-20

Copyright © 2026