REST API
Recording Entry API
Overview
Transcript entry (sentence) editing API. Provides the ability for users to correct STT recognition errors.
PATCH /api/v1/tasks/{taskId}/entries/{sid}
Description
Modifies the original text (original_text) of a single sentence in a historical recording.
Design highlights:
- Preserves the original STT output: On the first edit, the system automatically backs up the original STT result to
original_text_raw, which you can trace back to at any time - No automatic retranslation: This endpoint only changes the original text; translation must be triggered by calling
GET /api/v1/sse/recordings/{taskId}/entries/{sid}/retranslate - Optimistic lock: You can pass
expected_revisionto prevent concurrent overwrites - Automatic TTS cache invalidation: After the original text changes, the TTS cache for that sentence in all languages is cleared
Limitations
- Only recordings that have finished processing (
processing_status === completed) are allowed; in-progress recordings returnrecording_not_completed - You can only edit recordings owned by the API Key holder
Authentication
Header: X-API-Key (see Authentication)
Request Parameters
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
taskId | string | Yes | Task ID (UUID) |
sid | number | Yes | Sentence ID (1-based) |
Body Parameters (JSON)
| Parameter | Type | Required | Description |
|---|---|---|---|
original_text | string | Yes | Corrected original text, 1–2000 characters |
expected_revision | number | No | Optimistic lock: the current transcript revision; a mismatch returns transcript_revision_conflict |
Request Example
# Direct overwrite (recommended: tasks path)
curl -X PATCH "https://vas-poc.vurbo.ai/api/v1/tasks/{taskId}/entries/5" \
-H "X-API-Key: vas_xxx" \
-H "Content-Type: application/json" \
-d '{ "original_text": "Corrected text" }'
# With optimistic lock
curl -X PATCH "https://vas-poc.vurbo.ai/api/v1/tasks/{taskId}/entries/5" \
-H "X-API-Key: vas_xxx" \
-H "Content-Type: application/json" \
-d '{ "original_text": "Corrected text", "expected_revision": 3 }'
Success Response
HTTP 200
{
"data": {
"sid": 5,
"original_text": "Corrected text",
"original_text_raw": "Original STT output",
"original_text_edited_at": "2026-05-06T10:30:00.000000Z",
"translated_texts": {
"en-US": "Stale previous translation; re-run via the retranslate endpoint"
},
"revision": 4
}
}
| Field | Type | Description |
|---|---|---|
sid | number | Sentence ID |
original_text | string | The corrected original text |
original_text_raw | string | The original STT output (backed up on the first edit) |
original_text_edited_at | string | Edit time (ISO 8601) |
translated_texts | object | Existing translations (not updated automatically; you must separately call the SSE retranslate endpoint) |
revision | number | The new revision after the write, used for the next optimistic lock |
Specific Error Codes
| Error Code | HTTP | Description |
|---|---|---|
recording_not_found | 404 | The recording does not exist or does not belong to this user |
recording_not_completed | 422 | The recording has not finished processing yet |
entry_not_found | 404 | The specified sentence could not be found |
entry_text_empty | 422 | The original text is empty |
entry_text_too_long | 422 | The original text exceeds the 2000-character limit |
transcript_revision_conflict | 409 | The revision does not match (it was modified by another request), or another write to the same transcript is in progress |
speaker_transcript_not_found | 404 | The transcript could not be found |
storage_upload_failed | 500 | Writing the transcript back to storage failed |
Typical Workflow: Edit + Automatic Retranslation
// 1. Get the current revision from historyTranscribe (via init_metadata or by reading it yourself)
const currentRevision = 3;
// 2. Edit the original text
const editResp = await fetch(`/api/v1/tasks/${id}/entries/${sid}`, {
method: 'PATCH',
headers: { 'X-API-Key': key, 'Content-Type': 'application/json' },
body: JSON.stringify({
original_text: 'Corrected text',
expected_revision: currentRevision,
}),
});
const { data } = await editResp.json();
// Use the returned data.revision; do not assume it equals expected_revision + 1
// 3. Trigger single-sentence retranslation (emits progress / translated / done events)
const sse = new EventSource(
`/api/v1/sse/recordings/${id}/entries/${sid}/retranslate`
+ `?expectedRevision=${data.revision}&api_key=${key}`
);
sse.addEventListener('translated', (e) => {
const { lang, text } = JSON.parse(e.data);
console.log(`${lang}: ${text}`);
});
sse.addEventListener('done', (e) => {
const { revision } = JSON.parse(e.data);
// Again, use the returned value: if another write happened in between, the number skips
sse.close();
});
Version: V1.24.1 Last Updated: 2026-09-28