Saltar a contenido

Inicio Rápido

¡Comienza con SubX API en minutos! Esta guía te guiará a través de tus primeras solicitudes a la API.

Requisitos Previos

Antes de comenzar, asegúrate de tener:

  • ✅ Creada una cuenta de SubX y generada una clave de API (ver Guía de Autenticación)
  • ✅ Tu cliente HTTP favorito o lenguaje de programación listo

Tu Primera Solicitud

Comencemos verificando el estado de salud de la API - este es el único endpoint que no requiere autenticación:

=== "cURL"

curl https://subx-api.duckdns.org/api/health
import requests

response = requests.get("https://subx-api.duckdns.org/api/health")
print(response.json())
const response = await fetch('https://subx-api.duckdns.org/api/health');
const data = await response.json();
console.log(data);

Respuesta Esperada:

{
  "status": "ok",
  "version": "1.0.0",
  "commit": "aaceda5"
}

Buscar Subtítulos

¡Ahora busquemos subtítulos! Reemplaza {TU_CLAVE_API} con tu clave de API real.

Búsqueda por Título

=== "cURL"

curl -X GET "https://subx-api.duckdns.org/api/subtitles/search?title=Dexter&limit=10" \
  -H "Authorization: Bearer {TU_CLAVE_API}"
import requests

headers = {"Authorization": "Bearer {TU_CLAVE_API}"}
params = {
    "title": "Dexter",
    "limit": 10
}

response = requests.get(
    "https://subx-api.duckdns.org/api/subtitles/search",
    headers=headers,
    params=params
)

data = response.json()
print(f"Encontrados {data['total']} subtítulos")
for subtitle in data['items']:
    print(f"- {subtitle['title']} ({subtitle['video_type']})")
package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "net/url"
)

func main() {
    apiKey := "{TU_CLAVE_API}"
    baseURL := "https://subx-api.duckdns.org/api/subtitles/search"

    // Construir parámetros de consulta
    params := url.Values{}
    params.Add("title", "Dexter")
    params.Add("limit", "10")

    // Crear solicitud
    req, _ := http.NewRequest("GET", baseURL+"?"+params.Encode(), nil)
    req.Header.Set("Authorization", "Bearer "+apiKey)

    // Enviar solicitud
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    // Parsear respuesta
    var result map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&result)
    fmt.Printf("Encontrados %v subtítulos\n", result["total"])
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Text.Json;

class Program
{
    static async Task Main()
    {
        var apiKey = "{TU_CLAVE_API}";
        var client = new HttpClient();

        client.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Bearer", apiKey);

        var url = "https://subx-api.duckdns.org/api/subtitles/search?title=Dexter&limit=10";
        var response = await client.GetAsync(url);
        var json = await response.Content.ReadAsStringAsync();

        var data = JsonSerializer.Deserialize<JsonElement>(json);
        Console.WriteLine($"Encontrados {data.GetProperty("total")} subtítulos");
    }
}

Respuesta Esperada:

{
  "items": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "video_type": "episode",
      "title": "Dexter",
      "season": 1,
      "episode": 1,
      "imdb_id": "tt0773262",
      "description": "Dexter S01E01 - Dexter",
      "uploader_name": "user123",
      "posted_at": "2024-01-15T10:30:00Z",
      "downloads": 1250
    }
  ],
  "total": 1
}

Búsqueda por ID de IMDb

Si conoces el ID de IMDb, puedes buscar directamente:

=== "cURL"

curl -X GET "https://subx-api.duckdns.org/api/subtitles/search?imdb_id=tt0773262&limit=20" \
  -H "Authorization: Bearer {TU_CLAVE_API}"
import requests

headers = {"Authorization": "Bearer {TU_CLAVE_API}"}
params = {
    "imdb_id": "tt0773262",  # Serie Dexter
    "limit": 20
}

response = requests.get(
    "https://subx-api.duckdns.org/api/subtitles/search",
    headers=headers,
    params=params
)

data = response.json()
print(f"Encontrados {data['total']} subtítulos para ID de IMDb tt0773262")

Descargar un Subtítulo

Una vez que hayas encontrado un subtítulo, descárgalo usando su ID:

=== "cURL"

# Descargar y guardar en archivo
curl -X GET "https://subx-api.duckdns.org/api/subtitles/550e8400-e29b-41d4-a716-446655440000/download" \
  -H "Authorization: Bearer {TU_CLAVE_API}" \
  -o subtitulo.srt
import requests

headers = {"Authorization": "Bearer {TU_CLAVE_API}"}
subtitle_id = "550e8400-e29b-41d4-a716-446655440000"

response = requests.get(
    f"https://subx-api.duckdns.org/api/subtitles/{subtitle_id}/download",
    headers=headers
)

# Guardar en archivo
with open("subtitulo.srt", "wb") as f:
    f.write(response.content)

print("¡Subtítulo descargado exitosamente!")
package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

func main() {
    apiKey := "{TU_CLAVE_API}"
    subtitleID := "550e8400-e29b-41d4-a716-446655440000"
    url := fmt.Sprintf("https://subx-api.duckdns.org/api/subtitles/%s/download", subtitleID)

    // Crear solicitud
    req, _ := http.NewRequest("GET", url, nil)
    req.Header.Set("Authorization", "Bearer "+apiKey)

    // Enviar solicitud
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    // Guardar en archivo
    file, _ := os.Create("subtitulo.srt")
    defer file.Close()

    io.Copy(file, resp.Body)
    fmt.Println("¡Subtítulo descargado exitosamente!")
}
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        var apiKey = "{TU_CLAVE_API}";
        var subtitleId = "550e8400-e29b-41d4-a716-446655440000";
        var client = new HttpClient();

        client.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Bearer", apiKey);

        var url = $"https://subx-api.duckdns.org/api/subtitles/{subtitleId}/download";
        var response = await client.GetAsync(url);

        var content = await response.Content.ReadAsByteArrayAsync();
        await File.WriteAllBytesAsync("subtitulo.srt", content);

        Console.WriteLine("¡Subtítulo descargado exitosamente!");
    }
}

Ejemplo Completo: Buscar y Descargar

Aquí hay un ejemplo completo que busca subtítulos y descarga el primer resultado:

=== "Python"

import requests
import os

# Configuración
API_KEY = os.getenv("SUBX_API_KEY")  # Usar variable de entorno
BASE_URL = "https://subx-api.duckdns.org"
headers = {"Authorization": f"Bearer {API_KEY}"}

def search_subtitles(title, limit=10):
    """Buscar subtítulos por título."""
    response = requests.get(
        f"{BASE_URL}/api/subtitles/search",
        headers=headers,
        params={"title": title, "limit": limit}
    )
    response.raise_for_status()
    return response.json()

def download_subtitle(subtitle_id, output_path):
    """Descargar un archivo de subtítulo."""
    response = requests.get(
        f"{BASE_URL}/api/subtitles/{subtitle_id}/download",
        headers=headers
    )
    response.raise_for_status()

    with open(output_path, "wb") as f:
        f.write(response.content)

    return output_path

# Flujo principal
if __name__ == "__main__":
    # Buscar subtítulos de "Dexter"
    print("Buscando subtítulos de Dexter...")
    results = search_subtitles("Dexter", limit=5)

    print(f"Encontrados {results['total']} subtítulos")

    if results['items']:
        # Descargar el primer resultado
        first_subtitle = results['items'][0]
        print(f"\nDescargando: {first_subtitle['title']}")

        subtitle_id = first_subtitle['id']
        output_file = f"{first_subtitle['title']}.srt"

        download_subtitle(subtitle_id, output_file)
        print(f"✓ Guardado en: {output_file}")
    else:
        print("No se encontraron subtítulos")
const API_KEY = process.env.SUBX_API_KEY;
const BASE_URL = 'https://subx-api.duckdns.org';

async function searchSubtitles(title, limit = 10) {
  const response = await fetch(
    `${BASE_URL}/api/subtitles/search?title=${encodeURIComponent(title)}&limit=${limit}`,
    {
      headers: { 'Authorization': `Bearer ${API_KEY}` }
    }
  );

  if (!response.ok) throw new Error('Búsqueda fallida');
  return await response.json();
}

async function downloadSubtitle(subtitleId, outputPath) {
  const response = await fetch(
    `${BASE_URL}/api/subtitles/${subtitleId}/download`,
    {
      headers: { 'Authorization': `Bearer ${API_KEY}` }
    }
  );

  if (!response.ok) throw new Error('Descarga fallida');

  const buffer = await response.arrayBuffer();
  const fs = require('fs').promises;
  await fs.writeFile(outputPath, Buffer.from(buffer));

  return outputPath;
}

// Flujo principal
async function main() {
  console.log('Buscando subtítulos de Dexter...');
  const results = await searchSubtitles('Dexter', 5);

  console.log(`Encontrados ${results.total} subtítulos`);

  if (results.items.length > 0) {
    const firstSubtitle = results.items[0];
    console.log(`\nDescargando: ${firstSubtitle.title}`);

    const outputFile = `${firstSubtitle.title}.srt`;
    await downloadSubtitle(firstSubtitle.id, outputFile);
    console.log(`✓ Guardado en: ${outputFile}`);
  } else {
    console.log('No se encontraron subtítulos');
  }
}

main().catch(console.error);

Manejo de Errores

Siempre maneja los errores de manera elegante en código de producción:

=== "Python"

import requests

headers = {"Authorization": f"Bearer {API_KEY}"}

try:
    response = requests.get(
        "https://subx-api.duckdns.org/api/subtitles/search",
        headers=headers,
        params={"title": "Dexter"}
    )
    response.raise_for_status()  # Lanzar excepción para códigos de estado 4xx/5xx
    data = response.json()

except requests.exceptions.HTTPError as e:
    if e.response.status_code == 401:
        print("❌ Clave de API inválida")
    elif e.response.status_code == 429:
        print("❌ Límite de tasa excedido")
    else:
        print(f"❌ Error HTTP: {e}")

except requests.exceptions.RequestException as e:
    print(f"❌ Solicitud fallida: {e}")

Códigos de Respuesta Comunes

Código Significado Descripción
200 OK Solicitud exitosa
400 Solicitud Incorrecta Parámetros inválidos
401 No Autorizado Clave de API faltante o inválida
404 No Encontrado Recurso no encontrado
429 Demasiadas Solicitudes Límite de tasa excedido
500 Error Interno del Servidor Error del servidor

Próximos Pasos

Ahora que has hecho tus primeras solicitudes, explora las capacidades completas de la API: