REST API

任務 API

端點總覽

方法端點說明
GET/api/v1/tasks取得任務列表
DELETE/api/v1/tasks/{taskId}刪除任務
PUT/api/v1/tasks/{taskId}/pin更新釘選狀態
PUT/api/v1/tasks/{taskId}/read標記已讀
PATCH/api/v1/tasks/{taskId}/name更新任務名稱
POST/api/v1/tasks/{taskId}/force-fail手動強制將任務標記為失敗
POST/api/v1/tasks/{taskId}/retry重新處理已失敗的任務
PUT/api/v1/tasks/batch/pin批次更新釘選狀態
DELETE/api/v1/tasks/batch批次刪除任務
GET/api/v1/tasks/{taskId}/audio/export下載任務音檔
GET/api/v1/tasks/{taskId}/transcript/export下載逐字稿(TXT / SRT / SBV / VTT / CSV)

GET /api/v1/tasks

功能說明

取得目前使用者的錄音任務列表。可透過 status 參數篩選不同處理階段的任務,或用 task_ids[] 只查指定的任務。

認證方式

Header:X-API-Key(詳見 認證機制)

請求參數

參數位置類型必填預設值說明
statusquerystring否completed篩選條件:completed(已完成)/ active(進行中)/ all(全部)
task_ids[]querystring[]否—只查這些任務(每個元素為 UUID,1~100 筆)

status 篩選說明

值回傳任務說明
completedprocessing_status = completed預設值,向後相容。只回傳處理完成的任務
activeprocessing_status IN (recording, importing, uploading, processing)進行中的任務(即時錄音中、音檔匯入中、上傳中、處理中)
all不篩選回傳所有任務(含進行中和已完成)

task_ids 篩選說明

  • 只回傳清單內、屬於目前帳號的任務;不存在或不屬於目前帳號的 ID 會直接略過,不會回錯誤。
  • status 照樣套用:沒帶 status 時仍只回傳已完成的任務。要不論狀態查詢指定任務,請加 status=all。
  • 回應格式與不帶 task_ids 時相同。
  • 超過 100 筆、格式不是 UUID,或 task_ids 不是陣列(例如沒加 [] 的 task_ids=<UUID>),會回 422 validation_failed。

請求範例

# 預設:只回傳已完成的任務(向後相容)
curl -X GET "https://vas-poc.vurbo.ai/api/v1/tasks" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW"

# 查詢進行中的任務
curl -X GET "https://vas-poc.vurbo.ai/api/v1/tasks?status=active" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW"

# 只查指定的任務(不論狀態,需加 status=all)
curl -G "https://vas-poc.vurbo.ai/api/v1/tasks" \
  --data-urlencode "task_ids[]=550e8400-e29b-41d4-a716-446655440000" \
  --data-urlencode "task_ids[]=6ba7b810-9dad-11d1-80b4-00c04fd430c8" \
  --data-urlencode "status=all" \
  -H "X-API-Key: vas_aB3dE5fG7hI9jK1lM3nO5pQ7rS9tU1vW"

成功回應

HTTP 200

{
  "data": {
    "tasks": [
      {
        "task_id": "550e8400-e29b-41d4-a716-446655440000",
        "title": "會議記錄",
        "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"
      }
    ]
  }
}

回應欄位說明

欄位類型說明
data.tasksarray任務列表
data.tasks[].task_idstring任務 ID(UUID)
data.tasks[].titlestring任務標題
data.tasks[].typestring錄音類型
data.tasks[].type_sourcestring來源類型(realtime / import / broadcast)
data.tasks[].duration_msnumber錄音時長(毫秒)
data.tasks[].duration_formattedstring格式化時長(分:秒)
data.tasks[].transcription_languagesarray | null轉錄語言列表(無轉錄語言時為 null)
data.tasks[].translation_languagesarray | null翻譯語言列表(無翻譯語言時為 null,例如 conversation 模式或 import 未設定翻譯語言)
data.tasks[].created_atstring建立時間(ISO 8601)
data.tasks[].processing_statusstring處理狀態(見下方說明)
data.tasks[].is_pinnedboolean是否已釘選
data.tasks[].is_unreadboolean是否未讀
data.tasks[].summary_modestring | null摘要模式:"builtin" / "custom" / null(未生成摘要時為 null)
data.tasks[].summary_templatestring | nulleffective slug — builtin → 內建模板 slug;custom → 客戶 slug(即 request 端的 prompt_slug,pass-through 追溯用)
data.tasks[].summary_languagestring | null摘要語言。錄音時未指定摘要語言,一般為第一個轉錄語言;互譯模式有指定 active_language 時為該語言。沒有摘要的任務可能為 null(與歷史紀錄 init_metadata 的 summary_language 相同)

processing_status 狀態說明

Recording 的處理狀態會隨處理進度即時更新:

狀態說明場景
recording即時錄音進行中即時錄音、廣播
importing音檔匯入處理中音檔匯入
uploading上傳至雲端儲存中錄音停止後、匯入完成後
pending待處理(保留向下相容)僅出現於舊資料;新建紀錄不會進入此狀態
processing語音辨識與翻譯處理中上傳完成後
completed處理完成最終狀態
failed處理失敗最終狀態

狀態流轉:

即時錄音/廣播:recording → uploading → processing → completed / failed
音檔匯入:    importing → uploading → processing → completed / failed

pending 狀態說明:保留供舊資料相容,新建紀錄不會進入此狀態。force-fail 仍接受處於 pending 的紀錄,以便清理歷史殘留資料。

特有錯誤碼

錯誤碼HTTP 狀態碼說明處理建議
validation_failed422參數驗證失敗確認 task_ids 為 UUID 陣列且為 1~100 筆

DELETE /api/v1/tasks/{taskId}

功能說明

刪除指定的任務。刪除是永久的,無法復原:任務連同其音檔、逐字稿、摘要、翻譯與匯入原檔會一併移除,之後查詢、匯出、重翻都無法再取得。

仍在處理中的任務不能刪除(processing_status 為 recording、importing、uploading、pending、processing,或該任務的匯入仍在處理中),會回 422 invalid_processing_status。請等它完成或失敗後再刪;若任務卡住不動,可先用 POST /api/v1/tasks/{taskId}/force-fail 標為失敗;但匯入仍在處理中的任務無法以此解除,需等匯入結束後再刪。

認證方式

Header:X-API-Key(詳見 認證機制)

請求參數

參數位置類型必填說明
taskIdpathstring是任務 ID(UUID)

請求範例

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

成功回應

HTTP 200

{
  "message": "任務已刪除"
}

回應欄位說明

欄位類型說明
messagestring操作結果訊息

特有錯誤碼

錯誤碼HTTP 狀態碼說明處理建議
recording_not_found404找不到指定的錄音確認 taskId 正確
invalid_processing_status422任務仍在處理中,不能刪除等任務完成或失敗後再刪;卡住的錄音可先 force-fail,匯入仍在處理中則需等匯入結束

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

功能說明

更新任務的釘選狀態。釘選的任務會在列表中優先顯示。

認證方式

Header:X-API-Key(詳見 認證機制)

請求參數

參數位置類型必填說明
taskIdpathstring是任務 ID(UUID)
is_pinnedbodyboolean是釘選狀態

請求範例

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}'

成功回應

HTTP 200

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

回應欄位說明

欄位類型說明
data.is_pinnedboolean更新後的釘選狀態

特有錯誤碼

錯誤碼HTTP 狀態碼說明處理建議
recording_not_found404找不到指定的錄音確認 taskId 正確
validation_failed422參數驗證失敗確認 is_pinned 為布林值

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

功能說明

將任務標記為已讀。

認證方式

Header:X-API-Key(詳見 認證機制)

請求參數

參數位置類型必填說明
taskIdpathstring是任務 ID(UUID)

請求範例

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

成功回應

HTTP 200

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

回應欄位說明

欄位類型說明
data.is_unreadboolean更新後的未讀狀態(固定為 false)

特有錯誤碼

錯誤碼HTTP 狀態碼說明處理建議
recording_not_found404找不到指定的錄音確認 taskId 正確

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

功能說明

更新指定任務的名稱。名稱長度最大為 60 字元(由伺服器設定控制)。

認證方式

Header:X-API-Key(詳見 認證機制)

請求參數

參數位置類型必填說明
taskIdpathstring是任務 ID(UUID)
namebodystring是任務名稱(最大 60 字元)

請求範例

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": "產品會議討論"}'

成功回應

HTTP 200

{
  "message": "錄音名稱已更新",
  "data": {
    "task_id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "產品會議討論",
    "name_source": "user"
  }
}

回應欄位說明

欄位類型說明
messagestring操作結果訊息
data.task_idstring任務 ID(UUID)
data.namestring更新後的任務名稱
data.name_sourcestring名稱來源:default(系統預設)/ llm(AI 生成)/ user(使用者自訂)

特有錯誤碼

錯誤碼HTTP 狀態碼說明處理建議
not_found404錄音已被刪除一般不存在的 taskId 會先在參數驗證階段回 422 validation_failed,只有已刪除的任務才走到這裡
recording_unauthorized403無權限操作此錄音確認任務屬於該用戶
validation_failed422驗證失敗確認 name 不為空且長度不超過 60 字元

PUT /api/v1/tasks/batch/pin

功能說明

批次更新多個任務的釘選狀態。單次請求最多可操作 100 筆任務。僅會影響屬於當前用戶的任務,不屬於該用戶的 ID 會被忽略。

認證方式

Header:X-API-Key(詳見 認證機制)

請求參數

參數位置類型必填說明
task_idsbodyarray是任務 ID 陣列(每個元素為 UUID,最多 100 筆)
is_pinnedbodyboolean是釘選狀態

請求範例

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
  }'

成功回應

HTTP 200

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

回應欄位說明

欄位類型說明
data.affected_countnumber實際被更新的任務數量

特有錯誤碼

錯誤碼HTTP 狀態碼說明處理建議
validation_failed422參數驗證失敗確認 task_ids 為 UUID 陣列且不超過 100 筆,is_pinned 為布林值

DELETE /api/v1/tasks/batch

功能說明

批次刪除多個任務。刪除是永久的,無法復原,範圍與單筆刪除相同。單次請求最多可操作 100 筆任務。僅會影響屬於當前用戶的任務,不屬於該用戶的 ID 會被忽略。

仍在處理中的任務會被跳過、不刪除,並列在回應的 skipped_task_ids;其餘任務照常刪除,整批不會因此失敗。

認證方式

Header:X-API-Key(詳見 認證機制)

請求參數

參數位置類型必填說明
task_idsbodyarray是任務 ID 陣列(每個元素為 UUID,最多 100 筆)

請求範例

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"
    ]
  }'

成功回應

HTTP 200

{
  "data": {
    "affected_count": 2,
    "skipped_task_ids": []
  }
}

回應欄位說明

欄位類型說明
data.affected_countnumber實際被刪除的任務數量
data.skipped_task_idsstring[]因仍在處理中而未刪除的任務 ID。全部照請求刪除時為空陣列。不屬於當前用戶的 ID 不會出現在這裡

特有錯誤碼

錯誤碼HTTP 狀態碼說明處理建議
validation_failed422參數驗證失敗確認 task_ids 為 UUID 陣列且不超過 100 筆

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

功能說明

下載指定任務的原始錄音音檔。回應為二進位音訊流並附加 Content-Disposition: attachment 標頭,瀏覽器或下載工具會直接將內容儲存為檔案。檔名會優先使用錄音名稱(經清洗過的檔名),若名稱為空則退回 audio。

與 音訊串流 API(GET /api/v1/sse/audio/{taskId})的差異:

  • 本端點:離線下載用途;回應附 Content-Disposition: attachment 標頭;不支援 Range Request。
  • 音訊串流:播放用途;支援 HTTP Range Request 以便拖曳快進;回應不強制下載。

認證方式

Header:X-API-Key(詳見 認證機制)

請求參數

參數位置類型必填說明
taskIdpathstring是任務 ID(UUID)

請求範例

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

提示:curl -OJ 會讓 curl 依伺服器回應的 Content-Disposition 自動命名儲存檔名。

成功回應

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

注意:絕大多數錄音以 M4A 容器(AAC 編碼)回傳,Content-Type 為 audio/mp4、副檔名為 .m4a。實際 Content-Type 依錄音儲存格式而定(少數歷史 / 廣播錄音可能為 audio/webm 或 audio/wav),請以 Response Header 為準。

特有錯誤碼

錯誤碼HTTP 狀態碼說明處理建議
recording_not_found404找不到指定的錄音,或音檔在雲端儲存中不存在確認 taskId 正確且錄音未被刪除
recording_audio_not_ready422音檔尚未上傳完成或處理中稍後重試;可先透過 GET /api/v1/tasks 確認 processing_status 為 completed
storage_download_failed500儲存服務下載失敗稍後重試;若持續失敗請聯絡支援

前端範例

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}`);
  }

  // 解析 Content-Disposition 取得建議檔名
  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

功能說明

下載指定任務的逐字稿,支援五種格式:純文字、SubRip 字幕、YouTube SBV 字幕、WebVTT 字幕、CSV 試算表。回應內容包含原文與所有翻譯語言;回應附 Content-Disposition: attachment 標頭以供直接下載。檔名會優先使用錄音名稱(經清洗後的檔名),若名稱為空則退回 transcript,並統一加上 -transcript.{ext} 後綴。

與 歷史逐字稿 SSE API(GET /api/v1/sse/history/transcribe/{taskId})的差異:

  • 本端點:離線下載用途;一次回傳完整檔案;可直接交給字幕軟體或試算表開啟。
  • SSE 歷史 API:漸進式載入用途;以 event stream 逐句推送原始結構資料(JSON 片段),供前端 UI 漸進渲染。

認證方式

Header:X-API-Key(詳見 認證機制)

請求參數

參數位置類型必填預設值說明
taskIdpathstring是—任務 ID(UUID)
formatquerystring否txt格式:txt / srt / sbv / vtt / csv

format 格式說明

格式時間格式內容結構典型用途
txt—每段一行 [說話者] 原文,翻譯以 4 個空白縮排為 [語言碼] 譯文閱讀、紀錄保存
srtHH:MM:SS,mmm含序號,每段時間軸後原文與翻譯各占一行SubRip 字幕(DaVinci Resolve、VLC 等)
sbvH:MM:SS.mmm無序號;時間軸以 , 分隔;原文與翻譯以 | 串接為單行(換行符會被替換為空白)YouTube 字幕上傳
vttHH:MM:SS.mmm以 WEBVTT 作為表頭,每段時間軸後原文與翻譯各占一行HTML5 <track> 字幕、Web 播放器
csvHH:MM:SS(無毫秒)UTF-8 BOM 開頭;欄位 index,start,end,speaker,text,<每個翻譯語言一欄>。某語言若整份都沒有可用譯文,該欄不會出現Excel、資料分析

請求範例

# 預設 TXT 格式
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

# 指定 SRT 格式
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(Excel 可直接開啟,UTF-8 BOM 確保中文不亂碼)
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

提示:curl -OJ 會讓 curl 依伺服器回應的 Content-Disposition 自動命名儲存檔名。

成功回應

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

注意:Content-Type 會依 format 參數動態決定:

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

輸出範例

假設逐字稿包含兩段中文錄音(zh-TW)及兩種翻譯(en-US、ja-JP):

TXT

[Alice] 你好,早安
    [en-US] Hello, good morning
    [ja-JP] おはよう
[Bob] 多謝
    [en-US] Thanks
    [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(檔案開頭含 UTF-8 BOM EF BB BF)

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

特有錯誤碼

錯誤碼HTTP 狀態碼說明處理建議
recording_not_found404找不到指定的錄音確認 taskId 正確且錄音未被刪除
recording_transcript_not_ready422逐字稿尚未產生完成或為空先透過 GET /api/v1/tasks 確認 processing_status = completed 後再呼叫
validation_failed422參數驗證失敗確認 format 為允許值之一(txt / srt / sbv / vtt / csv)
storage_download_failed500儲存服務下載失敗稍後重試;若持續失敗請聯絡支援

前端範例

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}`);
  }

  // 解析 Content-Disposition 取得建議檔名
  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

功能說明

將卡在非終態(recording / importing / uploading / pending / processing)的任務強制標記為失敗。使用情境:即時連線異常中斷但後續狀態通知未送達、或使用者主動放棄仍在上傳的錄音,不想再等系統自動清理逾時任務。

操作成功後:

  • processing_status 變為 failed,processing_error 寫入使用者提供的原因
  • 觸發 recording.failed webhook,payload.failure_source 為 user_forced,訂閱者可據此與「系統處理失敗」「逾時自動清理」區分來源
  • 後續若再推送 uploading / processing 狀態會被回應 409,終態保護生效

注意:已是終態(completed / failed)的任務呼叫此端點會得到 422。若想清除已完成的任務請改用 DELETE /api/v1/tasks/{taskId}。

認證方式

Header:X-API-Key(詳見 認證機制)

請求參數

參數位置類型必填預設值說明
taskIdpathstring是—任務 ID(UUID)
reasonbodystring | null否null失敗原因描述,最長 500 字元。留空時系統自動產生 User-forced failure (previous status: xxx)

請求範例

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

# 帶原因
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": "錄音端斷線太久,放棄等待"}'

成功回應

HTTP 200

{
  "data": {
    "task_id": "550e8400-e29b-41d4-a716-446655440000",
    "processing_status": "failed",
    "processing_error": "User-forced failure: 錄音端斷線太久,放棄等待 (previous status: recording)"
  }
}

回應欄位說明

欄位類型說明
data.task_idstring任務 ID(UUID)
data.processing_statusstring強制失敗後一律為 failed
data.processing_errorstring寫入 DB 的完整失敗原因(含前一個狀態)

特有錯誤碼

錯誤碼HTTP 狀態碼說明處理建議
recording_not_found404找不到指定的錄音,或錄音不屬於此使用者確認 taskId 正確且錄音未被刪除
invalid_processing_status422任務已是終態(completed / failed),不能強制失敗已完成的任務請改用 DELETE;已失敗的任務無需再次強制失敗
validation_failed422reason 超過 500 字元或 taskId 格式錯誤檢查 reason 長度與 taskId UUID 格式

前端範例

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

功能說明

將處於 failed 狀態的任務重新排入處理佇列,用於暫時性的後端服務失效(如 LLM 服務忙碌、摘要服務短暫中斷)導致處理失敗、使用者想重試的情境。

前置條件

條件必須值
processing_statusfailed
audio_statussuccess
transcript_statussuccess

任一條件不符會回 422 invalid_processing_status。若音檔或逐字稿尚未上傳完成,重試會立即再次失敗(因為找不到處理來源),因此此端點會提前擋下,避免無效的重試循環。

即使前置條件都符合,若同一筆任務仍有處理作業尚未結束,會回 409 task_already_processing,且任務狀態不會被改動;稍候再送出同一個請求即可。

注意:任務失敗後系統會自動再試數次。這段期間 processing_status 可能已經是 failed,而重試仍會收到 409 —— 代表自動重試尚未結束,隔幾分鐘再送出同一個請求即可。

操作成功後:

  • processing_status 變為 processing,processing_error 清空
  • 任務重新排入處理;系統保證處理端讀到的是更新後的狀態,不會用舊狀態重跑
  • 不會觸發 webhook(僅在 Job 完成時才觸發 recording.completed / recording.failed)

認證方式

Header:X-API-Key(詳見 認證機制)

請求參數

參數位置類型必填預設值說明
taskIdpathstring是—任務 ID(UUID)

請求範例

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

成功回應

HTTP 200

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

特有錯誤碼

錯誤碼HTTP 狀態碼說明details 欄位處理建議
recording_not_found404找不到指定的錄音,或錄音不屬於此使用者—確認 taskId 正確
invalid_processing_status422任務不在 failed 狀態details.current_status只有 failed 的任務可 retry
invalid_processing_status422音檔 / 逐字稿未完整上傳details.audio_status、details.transcript_status請先確認來源是否完整;若錄音源頭已毀損,建議改用 force-fail 收尾後重新錄製
task_already_processing409同一筆任務仍有處理作業尚未結束details.task_id稍候再送出同一個請求,不需更動任何參數

前端範例

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();
}

版本:V1.24.1 最後更新:2026-09-29

Copyright © 2026