Obtener Subtítulo¶
Recupera información detallada sobre un subtítulo específico por su ID.
Endpoint¶
GET /api/subtitles/{subtitle_id}
Autenticación¶
✅ Autenticación requerida - Incluye tu clave de API en el header Authorization.
Descripción¶
Este endpoint recupera información completa sobre un único subtítulo usando su UUID único. Úsalo cuando ya tengas un ID de subtítulo de un resultado de búsqueda y quieras obtener sus detalles completos.
Parámetros de Path¶
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
subtitle_id |
string (UUID) | Sí | Identificador único del subtítulo |
Ejemplos de Solicitud¶
=== "cURL"
curl -X GET "https://subx-api.duckdns.org/api/subtitles/550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer {TU_CLAVE_API}"
import requests
subtitle_id = "550e8400-e29b-41d4-a716-446655440000"
headers = {"Authorization": "Bearer {TU_CLAVE_API}"}
response = requests.get(
f"https://subx-api.duckdns.org/api/subtitles/{subtitle_id}",
headers=headers
)
subtitle = response.json()
print(f"Title: {subtitle['title']}")
print(f"Downloads: {subtitle['downloads']}")
package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
apiKey := "{TU_CLAVE_API}"
subtitleID := "550e8400-e29b-41d4-a716-446655440000"
url := fmt.Sprintf("https://subx-api.duckdns.org/api/subtitles/%s", subtitleID)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer "+apiKey)
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
var subtitle map[string]interface{}
json.NewDecoder(resp.Body).Decode(&subtitle)
fmt.Printf("Title: %v\n", subtitle["title"])
fmt.Printf("Downloads: %v\n", subtitle["downloads"])
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.Json;
using System.Threading.Tasks;
var subtitleId = "550e8400-e29b-41d4-a716-446655440000";
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "{TU_CLAVE_API}");
var url = $"https://subx-api.duckdns.org/api/subtitles/{subtitleId}";
var response = await client.GetAsync(url);
var json = await response.Content.ReadAsStringAsync();
var subtitle = JsonSerializer.Deserialize<JsonElement>(json);
Console.WriteLine($"Title: {subtitle.GetProperty("title")}");
Console.WriteLine($"Downloads: {subtitle.GetProperty("downloads")}");
const subtitleId = '550e8400-e29b-41d4-a716-446655440000';
const response = await fetch(
`https://subx-api.duckdns.org/api/subtitles/${subtitleId}`,
{
headers: {
'Authorization': 'Bearer {TU_CLAVE_API}'
}
}
);
const subtitle = await response.json();
console.log(`Title: ${subtitle.title}`);
console.log(`Downloads: ${subtitle.downloads}`);
Respuesta¶
Respuesta Exitosa (200 OK)¶
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"video_type": "episode",
"title": "Dexter",
"season": 1,
"episode": 1,
"year": 2006,
"imdb_id": "tt0773262",
"description": "Dexter S01E01 - Dexter\nRelease: HDTV.XviD-LOL\nBlu-ray rip version also available",
"uploader_name": "user123",
"posted_at": "2024-01-15T10:30:00Z",
"downloads": 1250
}
Campos de Respuesta¶
| Campo | Tipo | Descripción |
|---|---|---|
id |
string (UUID) | Identificador único del subtítulo |
video_type |
string | Tipo: movie o episode |
title |
string | Título de la película/serie |
season |
integer | null | Número de temporada (para episodios) |
episode |
integer | null | Número de episodio (para episodios) |
year |
integer | null | Año de estreno de película o de la serie principal |
imdb_id |
string | null | Identificador de IMDb (ej., tt0773262) |
description |
string | null | Descripción del subtítulo/info de release |
uploader_name |
string | null | Nombre de usuario del subidor original |
posted_at |
string | Timestamp ISO 8601 |
downloads |
integer | Contador total de descargas (fuente + API) |
Códigos de Estado¶
| Código | Descripción |
|---|---|
| 200 | Éxito - Subtítulo encontrado |
| 401 | No Autorizado - Clave de API inválida o faltante |
| 404 | No Encontrado - El subtítulo no existe o está inactivo |
| 429 | Demasiadas Solicitudes - Límite de tasa excedido |
| 500 | Error Interno del Servidor |
Respuestas de Error¶
404 No Encontrado¶
Este error ocurre cuando:
- El ID del subtítulo no existe en la base de datos
- El subtítulo existe pero ha sido desactivado (is_active=false)
- El formato del ID es inválido (no es un UUID válido)
401 No Autorizado¶
Casos de Uso¶
1. Obtener Detalles del Subtítulo Después de Búsqueda¶
import requests
def search_and_get_details(title):
"""Search for subtitles and get details of first result."""
headers = {"Authorization": "Bearer {TU_CLAVE_API}"}
# Search
search_response = requests.get(
"https://subx-api.duckdns.org/api/subtitles/search",
headers=headers,
params={"title": title, "limit": 1}
)
results = search_response.json()
if not results['items']:
print(f"No subtitles found for '{title}'")
return None
# Get detailed info
subtitle_id = results['items'][0]['id']
detail_response = requests.get(
f"https://subx-api.duckdns.org/api/subtitles/{subtitle_id}",
headers=headers
)
return detail_response.json()
# Usage
subtitle = search_and_get_details("Breaking Bad")
if subtitle:
print(f"Title: {subtitle['title']}")
print(f"Description: {subtitle['description']}")
2. Validar que el Subtítulo Existe Antes de Descargar¶
import requests
def download_if_exists(subtitle_id):
"""Check if subtitle exists before attempting download."""
headers = {"Authorization": "Bearer {TU_CLAVE_API}"}
# First, verify subtitle exists
try:
response = requests.get(
f"https://subx-api.duckdns.org/api/subtitles/{subtitle_id}",
headers=headers
)
response.raise_for_status()
except requests.exceptions.HTTPError as e:
if e.response.status_code == 404:
print("Subtitle not found")
return False
raise
# Subtitle exists, proceed with download
download_response = requests.get(
f"https://subx-api.duckdns.org/api/subtitles/{subtitle_id}/download",
headers=headers
)
with open("subtitle.srt", "wb") as f:
f.write(download_response.content)
return True
3. Recuperación por Lotes de Múltiples Subtítulos¶
import requests
from concurrent.futures import ThreadPoolExecutor
def get_subtitle_details(subtitle_id, headers):
"""Get details for a single subtitle."""
response = requests.get(
f"https://subx-api.duckdns.org/api/subtitles/{subtitle_id}",
headers=headers
)
if response.status_code == 200:
return response.json()
return None
def get_multiple_subtitles(subtitle_ids):
"""Fetch details for multiple subtitles concurrently."""
headers = {"Authorization": "Bearer {TU_CLAVE_API}"}
with ThreadPoolExecutor(max_workers=5) as executor:
futures = [
executor.submit(get_subtitle_details, sub_id, headers)
for sub_id in subtitle_ids
]
results = [f.result() for f in futures]
# Filter out None values (failed requests)
return [r for r in results if r is not None]
# Usage
ids = [
"550e8400-e29b-41d4-a716-446655440000",
"660e9500-f39c-52e5-b827-557766551111",
"770fa611-g40d-63f6-c938-668877662222"
]
subtitles = get_multiple_subtitles(ids)
print(f"Retrieved {len(subtitles)} subtitles")
4. Mostrar Información del Subtítulo¶
import requests
from datetime import datetime
def display_subtitle_info(subtitle_id):
"""Fetch and display formatted subtitle information."""
headers = {"Authorization": "Bearer {TU_CLAVE_API}"}
response = requests.get(
f"https://subx-api.duckdns.org/api/subtitles/{subtitle_id}",
headers=headers
)
if response.status_code != 200:
print(f"Error: {response.status_code}")
return
sub = response.json()
print("=" * 60)
print(f"Title: {sub['title']}")
if sub['video_type'] == 'episode':
print(f"Type: TV Episode (S{sub['season']:02d}E{sub['episode']:02d})")
else:
print(f"Type: Movie")
if sub.get('imdb_id'):
print(f"IMDb: https://www.imdb.com/title/{sub['imdb_id']}/")
print(f"Uploader: {sub.get('uploader_name', 'Unknown')}")
print(f"Downloads: {sub['downloads']}")
posted = datetime.fromisoformat(sub['posted_at'].replace('Z', '+00:00'))
print(f"Posted: {posted.strftime('%Y-%m-%d %H:%M UTC')}")
if sub.get('description'):
print(f"\nDescription:\n{sub['description']}")
print("=" * 60)
# Usage
display_subtitle_info("550e8400-e29b-41d4-a716-446655440000")
Notas¶
- Este endpoint devuelve un único objeto de subtítulo (no envuelto en array
itemscomo búsqueda) - Los subtítulos inactivos (
is_active=false) devuelven errores 404 - El campo
downloadscombina tanto descargas de la fuente como descargas de la API - El campo
iden la respuesta es el UUID (igual que el parámetrosubtitle_id) - Para episodios, prefiere usar el ID de IMDb de la respuesta (puede ser específico del episodio)
Relación con Otros Endpoints¶
graph LR
A[Search] --> B[Get Subtitle]
B --> C[Download]
A --> C
- Search → Get Subtitle: Usa búsqueda para encontrar IDs, luego obtiene detalles
- Get Subtitle → Download: Verifica que el subtítulo existe antes de descargar
- Search → Download: Puede omitir "Get Subtitle" si la búsqueda proporciona suficiente información
Próximos Pasos¶
- Descargar Subtítulo - Descarga el archivo de subtítulo actual
- Buscar Subtítulos - Encuentra subtítulos para obtener IDs