Swift SDK for speedrun.com API

Complete API coverage β€’ Cross-platform β€’ Powerful CLI tools

Terminal
# Search for games
$ speedrun-cli games search "Mario"

# Get leaderboard
$ speedrun-cli leaderboard sm64 120-star --top 10

# Get user's personal bests
$ speedrun-cli user pb username
import SpeedrunKit

// Create a client
let client = SpeedrunClient()

// Search for games
let games = try await client.games.list(
    query: GameQuery(name: "Mario", max: 10),
    embeds: [.categories, .levels]
)

// Get leaderboard
let leaderboard = try await client.leaderboards.fullGame(
    game: "sm64",
    category: "120-star",
    query: LeaderboardQuery(top: 10),
    embeds: [.players]
)

Features

πŸš€

Modern Swift

Built with async/await, Codable, and protocol-oriented design

🌍

Cross-Platform

Works on macOS, iOS, tvOS, watchOS, Android, and Linux

⚑

High Performance

Optimized networking with automatic retries and rate limiting

πŸ”’

Type-Safe

Comprehensive type safety with detailed error handling

πŸ“š

Complete Coverage

100% API coverage including games, runs, users, and leaderboards

πŸ› οΈ

CLI Tools

Powerful command-line interface for testing and automation

Command Line Interface

A comprehensive CLI tool for interacting with the speedrun.com API

speedrun-cli games
# List popular games
$ speedrun-cli games list --orderby popularity

Found 20 games:
1. Super Mario 64 (sm64)
2. The Legend of Zelda: Ocarina of Time (oot)
3. Minecraft: Java Edition (mc)
...

# Search for specific game
$ speedrun-cli games search "Portal" --max 5

Searching for "Portal"...
1. Portal (portal)
2. Portal 2 (portal2)
3. Portal: Still Alive (portalsa)
...
speedrun-cli leaderboards
# Get game leaderboard
$ speedrun-cli leaderboard sm64 120-star --top 5

Super Mario 64 - 120 Star Leaderboard
=====================================
1. cheese          1:37:50 (WR)
2. Puncayshun     1:37:53
3. Liam           1:38:07
4. Simply         1:38:23
5. Dowsky         1:38:28

# Get category leaderboard with video links
$ speedrun-cli leaderboard oot any% --videos

Displaying runs with video links...
speedrun-cli users
# Get user profile
$ speedrun-cli user profile cheese

User: cheese
Location: United States
Twitch: cheese05
Signup: 2014-12-28


# Get user's personal bests
$ speedrun-cli user pb cheese --game sm64

cheese's Personal Bests in Super Mario 64:
- 120 Star: 1:37:50 (WR) πŸ₯‡
- 70 Star: 46:28 (2nd) πŸ₯ˆ
- 16 Star: 14:35 (5th)
speedrun-cli runs
# Get recent verified runs
$ speedrun-cli runs recent --status verified

Recent Verified Runs:
1. Super Mario 64 - 16 Star by runner123 (15:42)
2. Portal - Glitchless by speedster (18:23)
3. Celeste - Any% by dashmaster (27:15)
...

# Get run details
$ speedrun-cli run details abc123xyz

Run Details:
Game: Super Mario 64
Category: 70 Star
Time: 47:23
Status: Verified βœ“

SDK Examples

Comprehensive Swift API with async/await support

Authentication

// Configure with API key
let config = SpeedrunConfiguration(
    apiKey: "your-api-key"
)
let client = SpeedrunClient(configuration: config)

// Access authenticated endpoints
let profile = try await client.profile.getProfile()
let notifications = try await client.profile.getNotifications()

Error Handling

do {
    let games = try await client.games.list()
} catch let error as SpeedrunError {
    switch error {
    case .networkError(let underlying):
        print("Network error: \(underlying)")
    case .rateLimitExceeded:
        print("Rate limit hit, retry later")
    case .httpError(let code, let message):
        print("HTTP \(code): \(message ?? "Unknown")")
    default:
        print("Error: \(error)")
    }
}

Pagination

// Fetch all games with pagination
var allGames: [Game] = []
var offset = 0
let pageSize = 200

repeat {
    let page = try await client.games.list(
        query: GameQuery(max: pageSize, offset: offset)
    )
    
    allGames.append(contentsOf: page.data)
    
    if page.data.count < pageSize {
        break
    }
    
    offset += pageSize
} while true

print("Total games: \(allGames.count)")

Embedding Related Data

// Fetch game with embedded data
let game = try await client.games.get(
    "sm64",
    embeds: [.categories, .levels, .variables]
)

// Access embedded data directly
for category in game.categories?.data ?? [] {
    print("Category: \(category.name)")
}

// Get leaderboard with player data
let leaderboard = try await client.leaderboards.fullGame(
    game: "sm64",
    category: "120-star",
    embeds: [.players]
)

Installation

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/guitaripod/SpeedrunKit.git", from: "1.0.0")
]

CLI Installation

Terminal
# Clone and build
$ git clone https://github.com/guitaripod/SpeedrunKit.git
$ cd SpeedrunKit
$ swift build --product speedrun-cli -c release

# Install to /usr/local/bin
$ sudo cp .build/release/speedrun-cli /usr/local/bin/

Docker

Terminal
# Pull from Docker Hub
$ docker pull guitaripod/speedrunkit:latest

# Run CLI
$ docker run --rm guitaripod/speedrunkit