REST API

Tasks

Endpoint Overview

MethodEndpointDescription
GET/api/v1/tasksGet task list
DELETE/api/v1/tasks/{taskId}Delete task
PUT/api/v1/tasks/{taskId}/pinUpdate pin status
PUT/api/v1/tasks/{taskId}/readMark as read
PATCH/api/v1/tasks/{taskId}/nameUpdate task name
POST/api/v1/tasks/{taskId}/force-failManually force a task to be marked as failed
POST/api/v1/tasks/{taskId}/retryReprocess a failed task
PUT/api/v1/tasks/batch/pinBatch update pin status
DELETE/api/v1/tasks/batchBatch delete tasks
GET/api/v1/tasks/{taskId}/audio/exportDownload task audio
GET/api/v1/tasks/{taskId}/transcript/exportDownload transcript (TXT / SRT / SBV / VTT / CSV)

GET /api/v1/tasks

Description

Get the recording task list for the current user. Use the status parameter to filter tasks by processing stage.

Authentication

Header: X-API-Key (see Authentication)

Request Parameters

ParameterLocationTypeRequiredDefaultDescription
statusquerystringNocompletedFilter: completed (completed) / active (in progress) / all (all)

status Filter Details

ValueTasks ReturnedDescription
completedprocessing_status = completedDefault value, backward compatible. Returns only completed tasks
activeprocessing_status IN (recording, importing, uploading, processing)Tasks in progress (live recording, audio import, uploading, processing)
allNo filterReturns all tasks (including in-progress and completed)

Request Example

# Default: returns only completed tasks (backward compatible)
curl -X GET "https://vas-poc.vurbo.ai/api/v1/tasks" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW"

# Query in-progress tasks
curl -X GET "https://vas-poc.vurbo.ai/api/v1/tasks?status=active" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW"

Success Response

HTTP 200

{
  "data": {
    "tasks": [
      {
        "task_id": "550e8400-e29b-41d4-a716-446655440000",
        "title": "Meeting Notes",
        "type": "transcribe",
        "type_source": "realtime",
        "duration_ms": 60000,
        "duration_formatted": "1:00",
        "transcription_languages": ["zh-TW"],
        "translation_languages": ["en-US"],
        "created_at": "2026-02-25T10:00:00Z",
        "processing_status": "completed",
        "is_pinned": false,
        "is_unread": true,
        "summary_mode": "custom",
        "summary_template": "acme-meeting-v2",
        "summary_language": "zh-TW"
      }
    ]
  }
}

Response Field Details

FieldTypeDescription
data.tasksarrayTask list
data.tasks[].task_idstringTask ID (UUID)
data.tasks[].titlestringTask title
data.tasks[].typestringRecording type
data.tasks[].type_sourcestringSource type (realtime / import / broadcast)
data.tasks[].duration_msnumberRecording duration (milliseconds)
data.tasks[].duration_formattedstringFormatted duration (min:sec)
data.tasks[].transcription_languagesarray | nullTranscription language list (null when there is no transcription language)
data.tasks[].translation_languagesarray | nullTranslation language list (null when there is no translation language, e.g. conversation mode or an import with no translation language set)
data.tasks[].created_atstringCreation time (ISO 8601)
data.tasks[].processing_statusstringProcessing status (see below)
data.tasks[].is_pinnedbooleanWhether the task is pinned
data.tasks[].is_unreadbooleanWhether the task is unread
data.tasks[].summary_modestring | nullSummary mode: "builtin" / "custom" / null (null when no summary has been generated)
data.tasks[].summary_templatestring | nulleffective slug — builtin → built-in template slug; custom → customer slug (i.e. the prompt_slug from the request, pass-through for traceability)
data.tasks[].summary_languagestring | nullSummary output language

processing_status Details

The processing status of a recording is updated in real time as processing progresses:

StatusDescriptionScenario
recordingLive recording in progressLive recording, broadcast
importingAudio import in progressAudio import
uploadingUploading to cloud storageAfter recording stops, after import completes
pendingPending (kept for backward compatibility)Appears only in legacy data; newly created records never enter this status
processingSpeech recognition and translation in progressAfter upload completes
completedProcessing completeFinal status
failedProcessing failedFinal status

Status transitions:

Live recording/broadcast: recording → uploading → processing → completed / failed
Audio import:             importing → uploading → processing → completed / failed

About the pending status: Kept for backward compatibility with legacy data; newly created records never enter this status. force-fail still accepts records in pending so that leftover historical data can be cleaned up.

Specific Error Codes

This endpoint has no specific error codes; it may only return common authentication errors.


DELETE /api/v1/tasks/{taskId}

Description

Delete the specified task (soft delete). After deletion, the task no longer appears in the list.

Authentication

Header: X-API-Key (see Authentication)

Request Parameters

ParameterLocationTypeRequiredDescription
taskIdpathstringYesTask ID (UUID)

Request Example

curl -X DELETE "https://vas-poc.vurbo.ai/api/v1/tasks/550e8400-e29b-41d4-a716-446655440000" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW"

Success Response

HTTP 200

{
  "message": "Task deleted"
}

Response Field Details

FieldTypeDescription
messagestringOperation result message

Specific Error Codes

Error CodeHTTP StatusDescriptionSuggested Action
recording_not_found404Recording not foundVerify that taskId is correct
recording_unauthorized403Unauthorized to access this recordingVerify that the task belongs to this user

PUT /api/v1/tasks/{taskId}/pin

Description

Update the pin status of a task. Pinned tasks are shown first in the list.

Authentication

Header: X-API-Key (see Authentication)

Request Parameters

ParameterLocationTypeRequiredDescription
taskIdpathstringYesTask ID (UUID)
is_pinnedbodybooleanYesPin status

Request Example

curl -X PUT "https://vas-poc.vurbo.ai/api/v1/tasks/550e8400-e29b-41d4-a716-446655440000/pin" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW" \
  -H "Content-Type: application/json" \
  -d '{"is_pinned": true}'

Success Response

HTTP 200

{
  "data": {
    "is_pinned": true
  }
}

Response Field Details

FieldTypeDescription
data.is_pinnedbooleanUpdated pin status

Specific Error Codes

Error CodeHTTP StatusDescriptionSuggested Action
recording_not_found404Recording not foundVerify that taskId is correct
validation_failed422Parameter validation failedVerify that is_pinned is a boolean

PUT /api/v1/tasks/{taskId}/read

Description

Mark a task as read.

Authentication

Header: X-API-Key (see Authentication)

Request Parameters

ParameterLocationTypeRequiredDescription
taskIdpathstringYesTask ID (UUID)

Request Example

curl -X PUT "https://vas-poc.vurbo.ai/api/v1/tasks/550e8400-e29b-41d4-a716-446655440000/read" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW"

Success Response

HTTP 200

{
  "data": {
    "is_unread": false
  }
}

Response Field Details

FieldTypeDescription
data.is_unreadbooleanUpdated unread status (always false)

Specific Error Codes

Error CodeHTTP StatusDescriptionSuggested Action
recording_not_found404Recording not foundVerify that taskId is correct

PATCH /api/v1/tasks/{taskId}/name

Description

Update the name of the specified task. The maximum name length is 60 characters (controlled by the RECORDING_NAME_MAX_LENGTH environment variable).

Authentication

Header: X-API-Key (see Authentication)

Request Parameters

ParameterLocationTypeRequiredDescription
taskIdpathstringYesTask ID (UUID)
namebodystringYesTask name (max 60 characters)

Request Example

curl -X PATCH "https://vas-poc.vurbo.ai/api/v1/tasks/550e8400-e29b-41d4-a716-446655440000/name" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW" \
  -H "Content-Type: application/json" \
  -d '{"name": "Product Meeting Discussion"}'

Success Response

HTTP 200

{
  "message": "Recording name updated",
  "data": {
    "task_id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Product Meeting Discussion",
    "name_source": "user"
  }
}

Response Field Details

FieldTypeDescription
messagestringOperation result message
data.task_idstringTask ID (UUID)
data.namestringUpdated task name
data.name_sourcestringName source: default (system default) / llm (AI generated) / user (user defined)

Specific Error Codes

Error CodeHTTP StatusDescriptionSuggested Action
recording_not_found404Recording not foundVerify that taskId is correct
recording_unauthorized403Unauthorized to access this recordingVerify that the task belongs to this user
validation_failed422Validation failedVerify that name is not empty and does not exceed 60 characters

PUT /api/v1/tasks/batch/pin

Description

Batch update the pin status of multiple tasks. A single request can operate on up to 100 tasks. Only tasks belonging to the current user are affected; IDs that do not belong to this user are ignored.

Authentication

Header: X-API-Key (see Authentication)

Request Parameters

ParameterLocationTypeRequiredDescription
task_idsbodyarrayYesArray of task IDs (each element is a UUID, up to 100)
is_pinnedbodybooleanYesPin status

Request Example

curl -X PUT "https://vas-poc.vurbo.ai/api/v1/tasks/batch/pin" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW" \
  -H "Content-Type: application/json" \
  -d '{
    "task_ids": [
      "550e8400-e29b-41d4-a716-446655440000",
      "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
    ],
    "is_pinned": true
  }'

Success Response

HTTP 200

{
  "data": {
    "affected_count": 2
  }
}

Response Field Details

FieldTypeDescription
data.affected_countnumberNumber of tasks actually updated

Specific Error Codes

Error CodeHTTP StatusDescriptionSuggested Action
validation_failed422Parameter validation failedVerify that task_ids is a UUID array of no more than 100 entries, and is_pinned is a boolean

DELETE /api/v1/tasks/batch

Description

Batch delete multiple tasks (soft delete). A single request can operate on up to 100 tasks. Only tasks belonging to the current user are affected; IDs that do not belong to this user are ignored.

Authentication

Header: X-API-Key (see Authentication)

Request Parameters

ParameterLocationTypeRequiredDescription
task_idsbodyarrayYesArray of task IDs (each element is a UUID, up to 100)

Request Example

curl -X DELETE "https://vas-poc.vurbo.ai/api/v1/tasks/batch" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW" \
  -H "Content-Type: application/json" \
  -d '{
    "task_ids": [
      "550e8400-e29b-41d4-a716-446655440000",
      "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
    ]
  }'

Success Response

HTTP 200

{
  "data": {
    "affected_count": 2
  }
}

Response Field Details

FieldTypeDescription
data.affected_countnumberNumber of tasks actually deleted

Specific Error Codes

Error CodeHTTP StatusDescriptionSuggested Action
validation_failed422Parameter validation failedVerify that task_ids is a UUID array of no more than 100 entries

GET /api/v1/tasks/{taskId}/audio/export

Description

Download the original recording audio of the specified task. The response is a binary audio stream with a Content-Disposition: attachment header, so a browser or download tool saves the content directly as a file. The filename uses the recording name (sanitized) when available; if the name is empty, it falls back to audio.

Difference from the Audio Streaming API (GET /api/v1/sse/audio/{taskId}):

  • This endpoint: for offline download; the response includes a Content-Disposition: attachment header; Range Requests are not supported.
  • Audio streaming: for playback; supports HTTP Range Requests for seeking; the response does not force a download.

Authentication

Header: X-API-Key (see Authentication)

Request Parameters

ParameterLocationTypeRequiredDescription
taskIdpathstringYesTask ID (UUID)

Request Example

curl -X GET "https://vas-poc.vurbo.ai/api/v1/tasks/550e8400-e29b-41d4-a716-446655440000/audio/export" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW" \
  -OJ

Tip: curl -OJ lets curl automatically name the saved file based on the server's Content-Disposition response.

Success Response

HTTP 200

HTTP/1.1 200 OK
Content-Type: audio/mp4
Content-Length: 1234567
Content-Disposition: attachment; filename="audio.m4a"; filename*=UTF-8''%E6%9C%83%E8%AD%B0%E8%A8%98%E9%8C%84.m4a
Cache-Control: no-cache

Note: The vast majority of recordings are returned as an M4A container (AAC encoded), with Content-Type audio/mp4 and the .m4a extension. The actual Content-Type depends on the recording's storage format (a few legacy / broadcast recordings may be audio/webm or audio/wav), so rely on the response header.

Specific Error Codes

Error CodeHTTP StatusDescriptionSuggested Action
recording_not_found404Recording not found, or the audio file does not exist in cloud storageVerify that taskId is correct and the recording has not been deleted
recording_audio_not_ready422Audio not yet uploaded or still processingRetry later; you can first confirm via GET /api/v1/tasks that processing_status is completed
storage_download_failed500Storage service download failedRetry later; if it keeps failing, contact support

Frontend Example

async function downloadAudio(taskId, apiKey) {
  const response = await fetch(
    `https://vas-poc.vurbo.ai/api/v1/tasks/${taskId}/audio/export`,
    {
      headers: { 'X-API-Key': apiKey },
    }
  );

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Download failed: ${error.data?.message}`);
  }

  // Parse Content-Disposition to get the suggested filename
  const disposition = response.headers.get('Content-Disposition') || '';
  const match = disposition.match(/filename\*=UTF-8''([^;]+)/);
  const filename = match ? decodeURIComponent(match[1]) : `audio-${taskId}`;

  const blob = await response.blob();
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
}

GET /api/v1/tasks/{taskId}/transcript/export

Description

Download the transcript of the specified task in one of five formats: plain text, SubRip subtitles, YouTube SBV subtitles, WebVTT subtitles, or a CSV spreadsheet. The response content includes the original text and all translation languages; it carries a Content-Disposition: attachment header for direct download. The filename uses the recording name (sanitized) when available; if the name is empty, it falls back to transcript, and a -transcript.{ext} suffix is always appended.

Difference from the Transcript History SSE API (GET /api/v1/sse/history/transcribe/{taskId}):

  • This endpoint: for offline download; returns the complete file in one response; can be opened directly in subtitle software or a spreadsheet.
  • SSE history API: for progressive loading; pushes the raw structured data (JSON fragments) sentence by sentence as an event stream, for progressive rendering in a frontend UI.

Authentication

Header: X-API-Key (see Authentication)

Request Parameters

ParameterLocationTypeRequiredDefaultDescription
taskIdpathstringYesTask ID (UUID)
formatquerystringNotxtFormat: txt / srt / sbv / vtt / csv

format Details

FormatTime FormatContent StructureTypical Use
txtOne line per segment, [Speaker] original text, with translations indented by 4 spaces as [language code] translated textReading, recordkeeping
srtHH:MM:SS,mmmIncludes sequence numbers; after each timecode, the original text and translations each occupy one lineSubRip subtitles (DaVinci Resolve, VLC, etc.)
sbvH:MM:SS.mmmNo sequence numbers; timecodes separated by ,; original text and translations joined into a single line with | (line breaks are replaced with spaces)YouTube subtitle upload
vttHH:MM:SS.mmmUses WEBVTT as the header; after each timecode, the original text and translations each occupy one lineHTML5 <track> subtitles, web players
csvHH:MM:SS (no milliseconds)Starts with a UTF-8 BOM; columns index,start,end,speaker,text,<one column per translation language>Excel, data analysis

Request Example

# Default TXT format
curl -X GET "https://vas-poc.vurbo.ai/api/v1/tasks/550e8400-e29b-41d4-a716-446655440000/transcript/export" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW" \
  -OJ

# Specify SRT format
curl -X GET "https://vas-poc.vurbo.ai/api/v1/tasks/550e8400-e29b-41d4-a716-446655440000/transcript/export?format=srt" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW" \
  -OJ

# CSV (opens directly in Excel; the UTF-8 BOM keeps non-ASCII text from becoming garbled)
curl -X GET "https://vas-poc.vurbo.ai/api/v1/tasks/550e8400-e29b-41d4-a716-446655440000/transcript/export?format=csv" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW" \
  -OJ

Tip: curl -OJ lets curl automatically name the saved file based on the server's Content-Disposition response.

Success Response

HTTP 200

HTTP/1.1 200 OK
Content-Type: text/csv; charset=UTF-8
Content-Length: 2048
Content-Disposition: attachment; filename="transcript.csv"; filename*=UTF-8''%E6%9C%83%E8%AD%B0%E8%A8%98%E9%8C%84-transcript.csv
Cache-Control: no-cache

Note: Content-Type is determined dynamically by the format parameter:

FormatContent-Type
txttext/plain; charset=UTF-8
srtapplication/x-subrip
sbvtext/plain; charset=UTF-8
vtttext/vtt; charset=UTF-8
csvtext/csv; charset=UTF-8

Output Examples

Assume the transcript contains two English recording segments (en-US) with two translations (zh-TW, ja-JP):

TXT

[Alice] Hello, good morning
    [zh-TW] 你好,早安
    [ja-JP] おはよう
[Bob] Thanks
    [zh-TW] 多謝
    [ja-JP] ありがとう

SRT

1
00:00:00,500 --> 00:00:03,000
Hello, good morning
你好,早安
おはよう

2
00:00:03,000 --> 00:00:04,200
Thanks
多謝
ありがとう

SBV

0:00:00.500,0:00:03.000
Hello, good morning | 你好,早安 | おはよう

0:00:03.000,0:00:04.200
Thanks | 多謝 | ありがとう

VTT

WEBVTT

00:00:00.500 --> 00:00:03.000
Hello, good morning
你好,早安
おはよう

00:00:03.000 --> 00:00:04.200
Thanks
多謝
ありがとう

CSV (the file begins with a UTF-8 BOM EF BB BF)

index,start,end,speaker,text,zh-TW,ja-JP
1,00:00:00,00:00:03,Alice,"Hello, good morning",你好,早安,おはよう
2,00:00:03,00:00:04,Bob,Thanks,多謝,ありがとう

Specific Error Codes

Error CodeHTTP StatusDescriptionSuggested Action
recording_not_found404Recording not foundVerify that taskId is correct and the recording has not been deleted
recording_transcript_not_ready422Transcript not yet generated or emptyFirst confirm via GET /api/v1/tasks that processing_status = completed before calling
validation_failed422Parameter validation failedVerify that format is one of the allowed values (txt / srt / sbv / vtt / csv)
storage_download_failed500Storage service download failedRetry later; if it keeps failing, contact support

Frontend Example

async function downloadTranscript(taskId, apiKey, format = 'srt') {
  const response = await fetch(
    `https://vas-poc.vurbo.ai/api/v1/tasks/${taskId}/transcript/export?format=${format}`,
    {
      headers: { 'X-API-Key': apiKey },
    }
  );

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Download failed: ${error.data?.message}`);
  }

  // Parse Content-Disposition to get the suggested filename
  const disposition = response.headers.get('Content-Disposition') || '';
  const match = disposition.match(/filename\*=UTF-8''([^;]+)/);
  const filename = match
    ? decodeURIComponent(match[1])
    : `transcript-${taskId}.${format}`;

  const blob = await response.blob();
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
}

POST /api/v1/tasks/{taskId}/force-fail

Description

Force-mark as failed a task that is stuck in a non-terminal state (recording / importing / uploading / pending / processing). Use case: the upstream WebSocket connection broke abnormally but the follow-up status notification never arrived, or the user wants to abandon a recording that is still uploading and does not want to wait for the CheckStaleRecordings schedule (up to 30 minutes) to clean it up.

After a successful operation:

  • processing_status becomes failed, and processing_error is written with the reason provided by the user
  • A recording.failed webhook is triggered, with payload.failure_source set to user_forced, so subscribers can distinguish this source from "job execution failure" and "automatic stale scan"
  • When the backend later pushes uploading / processing to the internal API, it receives a 409, so the terminal-state protection takes effect

Note: Calling this endpoint on a task that is already in a terminal state (completed / failed) returns 422. To remove a completed task, use DELETE /api/v1/tasks/{taskId} instead.

Authentication

Header: X-API-Key (see Authentication)

Request Parameters

ParameterLocationTypeRequiredDefaultDescription
taskIdpathstringYesTask ID (UUID)
reasonbodystring | nullNonullFailure reason description, up to 500 characters. When empty, the system automatically generates User-forced failure (previous status: xxx)

Request Example

# Without a reason
curl -X POST "https://vas-poc.vurbo.ai/api/v1/tasks/550e8400-e29b-41d4-a716-446655440000/force-fail" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW"

# With a reason
curl -X POST "https://vas-poc.vurbo.ai/api/v1/tasks/550e8400-e29b-41d4-a716-446655440000/force-fail" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW" \
  -H "Content-Type: application/json" \
  -d '{"reason": "Recording client disconnected too long, giving up"}'

Success Response

HTTP 200

{
  "data": {
    "task_id": "550e8400-e29b-41d4-a716-446655440000",
    "processing_status": "failed",
    "processing_error": "User-forced failure: Recording client disconnected too long, giving up (previous status: recording)"
  }
}

Response Field Details

FieldTypeDescription
data.task_idstringTask ID (UUID)
data.processing_statusstringAlways failed after a forced failure
data.processing_errorstringThe complete failure reason written to the DB (including the previous status)

Specific Error Codes

Error CodeHTTP StatusDescriptionSuggested Action
recording_not_found404Recording not found, or the recording does not belong to this userVerify that taskId is correct and the recording has not been deleted
invalid_processing_status422The task is already in a terminal state (completed / failed) and cannot be forced to failFor completed tasks, use DELETE instead; failed tasks do not need to be force-failed again
validation_failed422reason exceeds 500 characters, or taskId has an invalid formatCheck the length of reason and the UUID format of taskId

Frontend Example

async function forceFailTask(taskId, apiKey, reason = null) {
  const body = reason ? JSON.stringify({ reason }) : undefined;
  const response = await fetch(
    `https://vas-poc.vurbo.ai/api/v1/tasks/${taskId}/force-fail`,
    {
      method: 'POST',
      headers: {
        'X-API-Key': apiKey,
        'Content-Type': 'application/json',
      },
      body,
    }
  );

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Force-fail failed: ${error.data?.message}`);
  }

  return await response.json();
}

POST /api/v1/tasks/{taskId}/retry

Description

Re-queue for processing (ProcessRecordingJob) a task that is in the failed state. This is for cases where a transient backend service failure (such as the LLM being rate limited or the summary service briefly going down) caused the job to fail and the user wants to retry.

Preconditions

ConditionRequired Value
processing_statusfailed
audio_statussuccess
transcript_statussuccess

If any condition is not met, 422 invalid_processing_status is returned. If the audio or transcript has not finished uploading, re-dispatching would immediately fail again (because the processor cannot find the source), so this endpoint blocks it in advance to avoid a retry loop.

After a successful operation:

  • processing_status becomes processing, and processing_error is cleared
  • ProcessRecordingJob is dispatched to the recordings queue in afterCommit() mode, ensuring the queue worker does not read the old value before the DB transaction commits
  • No webhook is triggered (recording.completed / recording.failed is triggered only when the job finishes)

Authentication

Header: X-API-Key (see Authentication)

Request Parameters

ParameterLocationTypeRequiredDefaultDescription
taskIdpathstringYesTask ID (UUID)

Request Example

curl -X POST "https://vas-poc.vurbo.ai/api/v1/tasks/550e8400-e29b-41d4-a716-446655440000/retry" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW"

Success Response

HTTP 200

{
  "data": {
    "task_id": "550e8400-e29b-41d4-a716-446655440000",
    "processing_status": "processing"
  }
}

Specific Error Codes

Error CodeHTTP StatusDescriptiondetails FieldSuggested Action
recording_not_found404Recording not found, or the recording does not belong to this userVerify that taskId is correct
invalid_processing_status422The task is not in the failed statedetails.current_statusOnly failed tasks can be retried
invalid_processing_status422Audio / transcript not fully uploadeddetails.audio_status, details.transcript_statusFirst confirm whether the source is complete; if the recording source is already corrupted, use force-fail to close it out and re-record

Frontend Example

async function retryTask(taskId, apiKey) {
  const response = await fetch(
    `https://vas-poc.vurbo.ai/api/v1/tasks/${taskId}/retry`,
    {
      method: 'POST',
      headers: { 'X-API-Key': apiKey },
    }
  );

  if (!response.ok) {
    const error = await response.json();
    const details = error.data?.details;
    if (details?.audio_status && details.audio_status !== 'success') {
      throw new Error(`Cannot retry: audio not ready (${details.audio_status})`);
    }
    throw new Error(`Retry failed: ${error.data?.message}`);
  }

  return await response.json();
}

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

Copyright © 2026