Quickstart¶
Get started with the SubX API in minutes! This guide will walk you through your first API requests.
Prerequisites¶
Before you begin, make sure you have:
- ✅ Created a SubX account and generated an API key (see Authentication Guide)
- ✅ Your favorite HTTP client or programming language ready
Your First Request¶
Let's start by checking the API health status - this is the only endpoint that doesn't require authentication:
=== "cURL"
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);
Expected Response:
Search for Subtitles¶
Now let's search for subtitles! Replace {YOUR_API_KEY_HERE} with your actual API key.
Search by Title¶
=== "cURL"
curl -X GET "https://subx-api.duckdns.org/api/subtitles/search?title=Dexter&limit=10" \
-H "Authorization: Bearer {YOUR_API_KEY_HERE}"
import requests
headers = {"Authorization": "Bearer {YOUR_API_KEY_HERE}"}
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"Found {data['total']} subtitles")
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 := "{YOUR_API_KEY_HERE}"
baseURL := "https://subx-api.duckdns.org/api/subtitles/search"
// Build query parameters
params := url.Values{}
params.Add("title", "Dexter")
params.Add("limit", "10")
// Create request
req, _ := http.NewRequest("GET", baseURL+"?"+params.Encode(), nil)
req.Header.Set("Authorization", "Bearer "+apiKey)
// Send request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
// Parse response
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Printf("Found %v subtitles\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 = "{YOUR_API_KEY_HERE}";
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($"Found {data.GetProperty("total")} subtitles");
}
}
Expected Response:
{
"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
}
Search by IMDb ID¶
If you know the IMDb ID, you can search directly:
=== "cURL"
curl -X GET "https://subx-api.duckdns.org/api/subtitles/search?imdb_id=tt0773262&limit=20" \
-H "Authorization: Bearer {YOUR_API_KEY_HERE}"
import requests
headers = {"Authorization": "Bearer {YOUR_API_KEY_HERE}"}
params = {
"imdb_id": "tt0773262", # Dexter series
"limit": 20
}
response = requests.get(
"https://subx-api.duckdns.org/api/subtitles/search",
headers=headers,
params=params
)
data = response.json()
print(f"Found {data['total']} subtitles for IMDb ID tt0773262")
Download a Subtitle¶
Once you've found a subtitle, download it using its ID:
=== "cURL"
# Download and save to file
curl -X GET "https://subx-api.duckdns.org/api/subtitles/550e8400-e29b-41d4-a716-446655440000/download" \
-H "Authorization: Bearer {YOUR_API_KEY_HERE}" \
-o subtitle.srt
import requests
headers = {"Authorization": "Bearer {YOUR_API_KEY_HERE}"}
subtitle_id = "550e8400-e29b-41d4-a716-446655440000"
response = requests.get(
f"https://subx-api.duckdns.org/api/subtitles/{subtitle_id}/download",
headers=headers
)
# Save to file
with open("subtitle.srt", "wb") as f:
f.write(response.content)
print("Subtitle downloaded successfully!")
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
apiKey := "{YOUR_API_KEY_HERE}"
subtitleID := "550e8400-e29b-41d4-a716-446655440000"
url := fmt.Sprintf("https://subx-api.duckdns.org/api/subtitles/%s/download", subtitleID)
// Create request
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "Bearer "+apiKey)
// Send request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
// Save to file
file, _ := os.Create("subtitle.srt")
defer file.Close()
io.Copy(file, resp.Body)
fmt.Println("Subtitle downloaded successfully!")
}
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 = "{YOUR_API_KEY_HERE}";
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("subtitle.srt", content);
Console.WriteLine("Subtitle downloaded successfully!");
}
}
Complete Example: Search and Download¶
Here's a complete example that searches for subtitles and downloads the first result:
=== "Python"
import requests
import os
# Configuration
API_KEY = os.getenv("SUBX_API_KEY") # Use environment variable
BASE_URL = "https://subx-api.duckdns.org"
headers = {"Authorization": f"Bearer {API_KEY}"}
def search_subtitles(title, limit=10):
"""Search for subtitles by title."""
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):
"""Download a subtitle file."""
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
# Main workflow
if __name__ == "__main__":
# Search for "Dexter" subtitles
print("Searching for Dexter subtitles...")
results = search_subtitles("Dexter", limit=5)
print(f"Found {results['total']} subtitles")
if results['items']:
# Download the first result
first_subtitle = results['items'][0]
print(f"\nDownloading: {first_subtitle['title']}")
subtitle_id = first_subtitle['id']
output_file = f"{first_subtitle['title']}.srt"
download_subtitle(subtitle_id, output_file)
print(f"✓ Saved to: {output_file}")
else:
print("No subtitles found")
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('Search failed');
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('Download failed');
const buffer = await response.arrayBuffer();
const fs = require('fs').promises;
await fs.writeFile(outputPath, Buffer.from(buffer));
return outputPath;
}
// Main workflow
async function main() {
console.log('Searching for Dexter subtitles...');
const results = await searchSubtitles('Dexter', 5);
console.log(`Found ${results.total} subtitles`);
if (results.items.length > 0) {
const firstSubtitle = results.items[0];
console.log(`\nDownloading: ${firstSubtitle.title}`);
const outputFile = `${firstSubtitle.title}.srt`;
await downloadSubtitle(firstSubtitle.id, outputFile);
console.log(`✓ Saved to: ${outputFile}`);
} else {
console.log('No subtitles found');
}
}
main().catch(console.error);
Error Handling¶
Always handle errors gracefully in production code:
=== "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() # Raise exception for 4xx/5xx status codes
data = response.json()
except requests.exceptions.HTTPError as e:
if e.response.status_code == 401:
print("❌ Invalid API key")
elif e.response.status_code == 429:
print("❌ Rate limit exceeded")
else:
print(f"❌ HTTP error: {e}")
except requests.exceptions.RequestException as e:
print(f"❌ Request failed: {e}")
Common Response Codes¶
| Code | Meaning | Description |
|---|---|---|
| 200 | OK | Request successful |
| 400 | Bad Request | Invalid parameters |
| 401 | Unauthorized | Missing or invalid API key |
| 404 | Not Found | Resource not found |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server error |
Next Steps¶
Now that you've made your first requests, explore the full API capabilities:
- API Reference - Complete endpoint documentation
- Code Examples - More advanced examples
- Rate Limits - Understanding rate limits