curl --request POST 'https://api.voicecheap.ai/v1/actions/subtitles_upload_import' \
--header "x-api-key: $VOICECHEAP_API_KEY" \
--header 'Content-Type: application/json' \
--data '{"url":"https://media.example.com/interview.mp4","filename":"interview.mp4","kind":"video_to_srt","requestId":"13579bdf-2468-4ace-8bdf-0123456789ab"}'
const input = {
url: 'https://media.example.com/interview.mp4',
filename: 'interview.mp4',
kind: 'video_to_srt',
requestId: '13579bdf-2468-4ace-8bdf-0123456789ab',
};
const response = await fetch('https://api.voicecheap.ai/v1/actions/subtitles_upload_import', {
method: 'POST',
headers: {
'x-api-key': process.env.VOICECHEAP_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify(input),
});
const body = await response.json();
if (!response.ok) throw new Error(body.code + ': ' + body.message);
console.log(body);
import os
import requests
response = requests.post(
"https://api.voicecheap.ai/v1/actions/subtitles_upload_import",
headers={"x-api-key": os.environ["VOICECHEAP_API_KEY"]},
json={"url": "https://media.example.com/interview.mp4", "filename": "interview.mp4", "kind": "video_to_srt", "requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"},
timeout=120,
)
body = response.json()
if not response.ok:
raise RuntimeError(f"{body.get('code')}: {body.get('message')}")
print(body)
{
"data": {
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab",
"status": "running",
"pollAction": "action_request_get",
"pollAfterSeconds": 5
},
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"
}
{
"data": {
"fileKey": "uploads/account-user/a1b2c3d4-e5f6-4789-8abc-def012345678-interview.mp4",
"fileName": "interview.mp4",
"fileSize": 1048576,
"durationSeconds": 60,
"mimeType": "video/mp4",
"uploadType": "video",
"readUrl": "https://media.example.com/uploads/account-user/a1b2c3d4-e5f6-4789-8abc-def012345678-interview.mp4"
},
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"
}
{
"data": {
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab",
"operation": "subtitles_upload_import",
"createdAt": 1792144800000,
"updatedAt": 1792144820000,
"status": "running",
"pollAfterSeconds": 5
},
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"
}
{
"data": {
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab",
"operation": "subtitles_upload_import",
"createdAt": 1792144800000,
"updatedAt": 1792144820000,
"status": "completed",
"resultStored": false,
"message": "The action completed. Retrieve its output from the corresponding history or resource action."
},
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"
}
Napisy
Zaimportuj multimedia z adresu URL (napisy)
Zaimportuj do konta bezpośredni publiczny adres URL HTTPS pliku audio lub wideo. Przekierowania i sieci prywatne są odrzucane; obowiązują limity pliku i czasu trwania. Użyj otrzymanego fileKey w akcji generowania.
POST
/
v1
/
actions
/
subtitles_upload_import
curl --request POST 'https://api.voicecheap.ai/v1/actions/subtitles_upload_import' \
--header "x-api-key: $VOICECHEAP_API_KEY" \
--header 'Content-Type: application/json' \
--data '{"url":"https://media.example.com/interview.mp4","filename":"interview.mp4","kind":"video_to_srt","requestId":"13579bdf-2468-4ace-8bdf-0123456789ab"}'
const input = {
url: 'https://media.example.com/interview.mp4',
filename: 'interview.mp4',
kind: 'video_to_srt',
requestId: '13579bdf-2468-4ace-8bdf-0123456789ab',
};
const response = await fetch('https://api.voicecheap.ai/v1/actions/subtitles_upload_import', {
method: 'POST',
headers: {
'x-api-key': process.env.VOICECHEAP_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify(input),
});
const body = await response.json();
if (!response.ok) throw new Error(body.code + ': ' + body.message);
console.log(body);
import os
import requests
response = requests.post(
"https://api.voicecheap.ai/v1/actions/subtitles_upload_import",
headers={"x-api-key": os.environ["VOICECHEAP_API_KEY"]},
json={"url": "https://media.example.com/interview.mp4", "filename": "interview.mp4", "kind": "video_to_srt", "requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"},
timeout=120,
)
body = response.json()
if not response.ok:
raise RuntimeError(f"{body.get('code')}: {body.get('message')}")
print(body)
{
"data": {
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab",
"status": "running",
"pollAction": "action_request_get",
"pollAfterSeconds": 5
},
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"
}
{
"data": {
"fileKey": "uploads/account-user/a1b2c3d4-e5f6-4789-8abc-def012345678-interview.mp4",
"fileName": "interview.mp4",
"fileSize": 1048576,
"durationSeconds": 60,
"mimeType": "video/mp4",
"uploadType": "video",
"readUrl": "https://media.example.com/uploads/account-user/a1b2c3d4-e5f6-4789-8abc-def012345678-interview.mp4"
},
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"
}
{
"data": {
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab",
"operation": "subtitles_upload_import",
"createdAt": 1792144800000,
"updatedAt": 1792144820000,
"status": "running",
"pollAfterSeconds": 5
},
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"
}
{
"data": {
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab",
"operation": "subtitles_upload_import",
"createdAt": 1792144800000,
"updatedAt": 1792144820000,
"status": "completed",
"resultStored": false,
"message": "The action completed. Retrieve its output from the corresponding history or resource action."
},
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"
}
Zaimportuj do konta bezpośredni publiczny adres URL HTTPS pliku audio lub wideo. Przekierowania i sieci prywatne są odrzucane; obowiązują limity pliku i czasu trwania. Użyj otrzymanego fileKey w akcji generowania.
Wymagane uprawnienia:
POST https://api.voicecheap.ai/v1/actions/subtitles_upload_import
Uwierzytelnianie i uprawnienia
string
wymagane
Wyślij klucz API VoiceCheap w tym nagłówku. Obsługiwany jest również nagłówek Authorization: Bearer z tym samym kluczem API. Tokeny dostępu OAuth są
akceptowane tylko przez MCP, a nie przez ten endpoint REST.
subtitles:write.
Wymagana jest aktywna płatna subskrypcja. Uprawnienia nie zmieniają ról w zespole, własności zasobów, kredytów na multimedia ani limitów planu.
Parametry
string
wymagane
Wartość tekstowa.Maksymalna długość: 4096. Format: “uri”.
string
Wartość tekstowa.Minimalna długość: 1. Maksymalna długość: 255. Wzorzec:
^[^/\\\r\n\0]+$.string
wymagane
Wartość tekstowa.Dozwolone wartości: “transcription”, “video_to_srt”, “add_subtitles”, “animated_captions”, “project”.
string
Opcjonalne na poziomie transportu: jeśli identyfikator zostanie pominięty, serwer doda go przed walidacją. Podaj własny, stały UUID v4, aby bezpiecznie odzyskać wynik po utracie odpowiedzi.Format: “uuid”. Wzorzec:
^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$.Pełny schemat danych wejściowych
Pełny schemat danych wejściowych
Poniższy JSON Schema zachowuje dokładne nazwy pól, typy zagnieżdżone, wartości domyślne, ograniczenia i akceptowane wartości udostępniane przez mechanizm wykrywania. Dodatkowe reguły zależności między polami znajdują się w uwagach do operacji.
{
"type": "object",
"properties": {
"url": {
"type": "string",
"maxLength": 4096,
"format": "uri"
},
"filename": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"pattern": "^[^/\\\\\\r\\n\\0]+$"
},
"kind": {
"type": "string",
"enum": ["transcription", "video_to_srt", "add_subtitles", "animated_captions", "project"]
},
"requestId": {
"description": "UUID v4 for this action. Reuse the same ID with identical arguments on retries.",
"type": "string",
"format": "uuid",
"pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
}
},
"required": ["url", "kind"],
"additionalProperties": false
}
Idempotencja
Dla każdej operacji zmieniającej dane użyj UUID v4 w requestId lub w nagłówku HTTP Idempotency-Key. Po awarii sieci użyj ponownie tego samego identyfikatora i identycznych argumentów. Jeśli podasz oba, muszą być zgodne. Ponowienie zapisanego żądania nie powtarza operacji ani nie zużywa kolejnego wywołania z miesięcznego limitu. Żądania zakończone błędem lub przerwane nie są automatycznie uruchamiane ponownie. Każda operacja zmieniająca dane może zwrócić HTTP 202, gdy ponowienie napotka to samo żądanie nadal w stanie running, nawet jeśli jej pierwsze wykonanie zwykle jest synchroniczne. Jeśli wykonanie się zakończyło, ale resultStored ma wartość false, ponowienie zwraca HTTP 200 z zapisanym stanem żądania zamiast pierwotnego wyniku. Pobierz wynik za pomocą akcji historii, wyniku lub pobierania właściwej dla danej domeny.Przykłady żądań
Zastąp przykładowe identyfikatory zasobów i klucze multimediów wartościami zwróconymi dla Twojego konta. Przy ponawianiu tej samej operacji zmieniającej dane zachowaj identyfikator żądania.curl --request POST 'https://api.voicecheap.ai/v1/actions/subtitles_upload_import' \
--header "x-api-key: $VOICECHEAP_API_KEY" \
--header 'Content-Type: application/json' \
--data '{"url":"https://media.example.com/interview.mp4","filename":"interview.mp4","kind":"video_to_srt","requestId":"13579bdf-2468-4ace-8bdf-0123456789ab"}'
const input = {
url: 'https://media.example.com/interview.mp4',
filename: 'interview.mp4',
kind: 'video_to_srt',
requestId: '13579bdf-2468-4ace-8bdf-0123456789ab',
};
const response = await fetch('https://api.voicecheap.ai/v1/actions/subtitles_upload_import', {
method: 'POST',
headers: {
'x-api-key': process.env.VOICECHEAP_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify(input),
});
const body = await response.json();
if (!response.ok) throw new Error(body.code + ': ' + body.message);
console.log(body);
import os
import requests
response = requests.post(
"https://api.voicecheap.ai/v1/actions/subtitles_upload_import",
headers={"x-api-key": os.environ["VOICECHEAP_API_KEY"]},
json={"url": "https://media.example.com/interview.mp4", "filename": "interview.mp4", "kind": "video_to_srt", "requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"},
timeout=120,
)
body = response.json()
if not response.ok:
raise RuntimeError(f"{body.get('code')}: {body.get('message')}")
print(body)
Odpowiedź
Ta operacja zwraca HTTP 202 podczas przetwarzania. Zapisz requestId i odpytuj action_request_get, podając ten identyfikator oraz nazwę pierwotnej operacji. Stany odpytywania to running, completed, failed i interrupted. Zakończony wynik może wskazywać osobne zadanie przetwarzania multimediów; kontynuuj za pomocą akcji stanu lub wyniku właściwej dla tej operacji. Zaimportowane odwołanie do multimediów należących do użytkownika wykonującego wywołanie, ze zweryfikowanym rozmiarem, czasem trwania, rodzajem multimediów i adresem URL odczytu. Jest to ukończony wynik akcji, dostępny po sprawdzeniu stanu.{
"data": {
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab",
"status": "running",
"pollAction": "action_request_get",
"pollAfterSeconds": 5
},
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"
}
{
"data": {
"fileKey": "uploads/account-user/a1b2c3d4-e5f6-4789-8abc-def012345678-interview.mp4",
"fileName": "interview.mp4",
"fileSize": 1048576,
"durationSeconds": 60,
"mimeType": "video/mp4",
"uploadType": "video",
"readUrl": "https://media.example.com/uploads/account-user/a1b2c3d4-e5f6-4789-8abc-def012345678-interview.mp4"
},
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"
}
{
"data": {
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab",
"operation": "subtitles_upload_import",
"createdAt": 1792144800000,
"updatedAt": 1792144820000,
"status": "running",
"pollAfterSeconds": 5
},
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"
}
{
"data": {
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab",
"operation": "subtitles_upload_import",
"createdAt": 1792144800000,
"updatedAt": 1792144820000,
"status": "completed",
"resultStored": false,
"message": "The action completed. Retrieve its output from the corresponding history or resource action."
},
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab"
}
Pola wyniku
| Pole | Opis |
|---|---|
data.fileKey | Ukończony plik referencyjny należący do użytkownika, przeznaczony do akcji generowania. |
data.fileName | Oczyszczona nazwa zaimportowanego pliku. |
data.fileSize | Pobrane bajty źródła. |
data.durationSeconds | Zbadany czas trwania źródła w sekundach. |
data.mimeType | Typ MIME multimediów określony na podstawie obsługiwanego rozszerzenia pliku. |
data.uploadType | audio lub video. |
data.readUrl | Tymczasowy adres URL do odczytu zaimportowanego źródła; generowanie używa fileKey. |
Odzyskaj żądanie i sprawdź jego stan
Używaj tego samego identyfikatora także po utracie połączenia. Jeśli resultStored ma wartość false, pobierz wynik za pomocą odpowiedniej akcji historii, wyniku lub pobierania. Nigdy nie uruchamiaj drugiego generowania tylko po to, aby sprawdzić postęp.curl --request POST 'https://api.voicecheap.ai/v1/actions/action_request_get' \
--header "x-api-key: $VOICECHEAP_API_KEY" \
--header 'Content-Type: application/json' \
--data '{"requestId":"13579bdf-2468-4ace-8bdf-0123456789ab","operation":"subtitles_upload_import"}'
HTTP 200
{
"data": {
"requestId": "13579bdf-2468-4ace-8bdf-0123456789ab",
"operation": "subtitles_upload_import",
"status": "completed",
"createdAt": 1792144800000,
"updatedAt": 1792144820000,
"resultStored": true,
"result": {
"fileKey": "uploads/account-user/a1b2c3d4-e5f6-4789-8abc-def012345678-interview.mp4",
"fileName": "interview.mp4",
"fileSize": 1048576,
"durationSeconds": 60,
"mimeType": "video/mp4",
"uploadType": "video",
"readUrl": "https://media.example.com/uploads/account-user/a1b2c3d4-e5f6-4789-8abc-def012345678-interview.mp4"
}
}
}
Uwagi do operacji
- Wymaga płatnej subskrypcji i uprawnienia do akcji. Osobisty plan narzędzi użytkownika wykonującego żądanie jest ponownie sprawdzany podczas wykonywania; zapisane narzędzia i referencje przesłanych plików należą do tego użytkownika, również gdy dane uwierzytelniające są powiązane z zespołem.
- Pomyślna akcja zużywa jedno wspólne miesięczne wywołanie API/MCP. Beginner pozwala na 500, Starter na 5,000, a Creator na 25,000 wywołań miesięcznie; Pro, Scale i Enterprise nie mają miesięcznego limitu. Nadal obowiązują limity na minutę: odpowiednio 30, 60, 120, 180, 300 i 600. Limity generowania narzędzi są odrębne.
- Użyj requestId w formacie UUID v4 lub identycznego nagłówka Idempotency-Key i przy ponawianiu zachowuj tę samą akcję, identyfikator i argumenty. Odtworzenie zapisanej odpowiedzi nie zużywa kolejnego miesięcznego wywołania.
- Prefiks przesyłania określa wymagane uprawnienie. tools używa transcription:write, subtitles używa subtitles:write, projects używa projects:write, a voices używa voices:write.
- Dla narzędzi, napisów i projektów kind przyjmuje transcription, video_to_srt, add_subtitles, animated_captions lub project. Wybrane kind określa limity procesu; prefiks nie wymusza kind.
- Wybrane kind stosuje własne limity: transcription 200 MiB; video_to_srt i add_subtitles 300 MiB; animated_captions 250 MiB i wyłącznie audio; project stosuje limit przesyłania z planu (Beginner 5 GiB, Starter 10 GiB, Creator 20 GiB, Pro 30 GiB, Scale 40 GiB, Enterprise 60 GiB). Samodzielne multimedia mogą trwać maksymalnie 2 godziny. Napisy dopuszczają 30 minut w planie Beginner i 60 minut w wyższych planach publicznych, z dodatkową tolerancją kontenera wynoszącą 2 sekundy. Projekt może trwać maksymalnie 2 godziny lub 3 godziny w planie Enterprise.
- Ta akcja działa asynchronicznie. Sprawdzaj action_request_get, podając nazwę operacji i pierwotny requestId, aż do ukończenia, zanim pobierzesz fileKey z wyniku.
- Użyj bezpośredniego publicznego adresu URL HTTPS pliku audio lub wideo. Przekierowania, dane uwierzytelniające, fragmenty, porty inne niż 443 i niepubliczne adresy DNS są odrzucane. Strona odtwarzania YouTube nie jest bezpośrednim adresem URL multimediów; użyj dedykowanych akcji YouTube.
- filename jest opcjonalne, gdy ścieżka adresu URL kończy się obsługiwaną nazwą pliku multimedialnego. Zapisywana nazwa pliku jest oczyszczana. Serwer bada rzeczywisty czas trwania przed zwróceniem fileKey.
- Import przygotowuje multimedia i zużywa jedno udane wywołanie z miesięcznego limitu integracji; dzienny limit generowania w narzędziu jest zużywany dopiero przez późniejsze generowanie.
Wykorzystanie
Każde pomyślne wywołanie zużywa jedno wywołanie z miesięcznego limitu API/MCP. Obowiązują również kredyty na multimedia oraz limity generowania danej operacji.Błędy
| Status HTTP | Kod | Znaczenie lub sposób rozwiązania |
|---|---|---|
| 400 | CREDENTIAL_IN_QUERY | Dane uwierzytelniające zostały podane w parametrze zapytania access_token lub api_key. Wysyłaj dane uwierzytelniające w nagłówkach. |
| 400 | EMPTY_MEDIA | Bezpośredni adres URL multimediów zwrócił pustą treść. |
| 400 | FILE_TOO_LARGE | Zadeklarowane lub pobrane źródło przekracza limit przesyłania dla wybranego kind. |
| 400 | IDEMPOTENCY_CONFLICT | Identyfikatory żądania w nagłówku i treści różnią się. |
| 400 | INVALID_FILE_TYPE | Podana lub uzyskana z adresu URL nazwa pliku nie ma obsługiwanego rozszerzenia dla wybranego kind. |
| 400 | INVALID_MEDIA_DURATION | Nie można ustalić czasu trwania pobranych mediów lub przekracza on limit planu dla wybranego rodzaju. |
| 400 | INVALID_MEDIA_TYPE | Typ zawartości odpowiedzi nie jest audio, video, application/ogg ani application/octet-stream. |
| 400 | INVALID_MEDIA_URL | Użyj bezpośredniego adresu URL HTTPS bez danych uwierzytelniających użytkownika, fragmentów ani portu innego niż 443; podaj prawidłową nazwę pliku multimedialnego. |
| 400 | INVALID_REQUEST_ID | requestId lub Idempotency-Key nie jest identyfikatorem UUID v4. |
| 400 | MEDIA_DOWNLOAD_REFUSED | Bezpośrednie pobieranie nie zwróciło HTTP 200. Przekierowania są odrzucane. |
| 400 | MEDIA_IMPORT_FAILED | Nie udało się pobrać, zbadać ani zapisać źródła; sprawdź jego publiczny adres URL i format multimediów. |
| 400 | MEDIA_URL_NOT_PUBLIC | Nie można rozwiązać nazwy hosta lub co najmniej jeden z uzyskanych adresów jest prywatny albo w inny sposób niepubliczny. |
| 400 | VALIDATION_ERROR | Argumenty nie spełniają schematu akcji lub podano nieznany argument. |
| 401 | API_KEY_EXPIRED | Klucz API wygasł. |
| 401 | INVALID_API_KEY | Podaj prawidłowy, niewygasły klucz API. |
| 401 | INVALID_CREDENTIAL | Nagłówek Authorization ma nieprawidłowy format lub jest sprzeczny z x-api-key. |
| 401 | MISSING_CREDENTIAL | Nie podano użytecznych danych uwierzytelniających w nagłówku lub przekroczyły one 4096 znaków. |
| 401 | USER_NOT_FOUND | Konto powiązane z poświadczeniem już nie istnieje. |
| 403 | ACCOUNT_UNAVAILABLE | Konto wykonujące operację lub konto rozliczeniowe jest niedostępne albo jest w trakcie usuwania. |
| 403 | AMBIGUOUS_TEAM_API_KEY | Użytkownik, do którego należą dane uwierzytelniające, należy do więcej niż jednego zespołu, więc kontekst rozliczeniowy jest niejednoznaczny. |
| 403 | INSUFFICIENT_SCOPE | Klucz API lub połączenie MCP nie ma uprawnienia wymaganego do wykonania tej akcji. |
| 403 | INTEGRATION_PLAN_UNSUPPORTED | Nie udało się zweryfikować limitów integracji konta. |
| 403 | PAID_SUBSCRIPTION_REQUIRED | Uwierzytelniony wywołujący nie ma już płatnej subskrypcji w chwili wykonywania tej akcji narzędzia. |
| 403 | SUBSCRIPTION_REQUIRED | Użyj aktywnej płatnej subskrypcji. |
| 403 | TEAM_OWNER_NOT_FOUND | Nie znaleziono konta faktycznego właściciela zespołu. |
| 409 | CONCURRENT_ACTION_LIMIT_REACHED | Na tym koncie działa już 10 akcji integracji. Sprawdzaj stan istniejącego żądania przed rozpoczęciem kolejnego. |
| 409 | IDEMPOTENCY_CONFLICT | Używaj ponownie identyfikatora wyłącznie z tą samą operacją i tymi samymi argumentami. |
| 429 | INTEGRATION_MONTHLY_LIMIT_REACHED | Wykorzystane i oczekujące wywołania osiągnęły wspólny miesięczny limit API/MCP. |
| 429 | INTEGRATION_RATE_LIMIT_REACHED | Konto osiągnęło limit integracji na minutę; sprawdź retryAfterSeconds. |
| 500 | INTERNAL_ERROR | Sprawdź stan zapisanego żądania i historię zasobu przed podjęciem decyzji o ponowieniu operacji zmieniającej dane. |
| 503 | ACTION_RESULT_UNAVAILABLE | Akcja została wykonana, ale nie udało się potwierdzić trwałego zapisania wyniku żądania. Sprawdzaj stan tej samej akcji i requestId oraz historię zasobu, zanim rozpoczniesz kolejny zapis. |
| 503 | SERVER_RESTARTING | Serwer jest uruchamiany ponownie. Spróbuj ponownie wkrótce i zachowaj ten sam identyfikator żądania dla operacji zmieniającej dane. |
{
"code": "INSUFFICIENT_SCOPE",
"message": "This credential does not permit the requested action.",
"status": 403,
"details": {
"requiredScopes": ["subtitles:write"]
}
}
Czy ta strona była pomocna?

