Skip to main content
Surge provides a comprehensive HTTP API for remote control and integration. The API is automatically available when running Surge in TUI or server mode.

API Overview

The Surge HTTP API allows you to:
  • Queue new downloads
  • List and monitor download progress
  • Control download state (pause, resume, delete)
  • Stream real-time events via Server-Sent Events (SSE)
  • Update download URLs for expired links

Server Configuration

Starting the API Server

# Start with auto-assigned or default port
surge server
The server binds to 0.0.0.0 (all interfaces) by default, making it accessible from:
  • localhost (127.0.0.1)
  • Your local network IP
  • Public IP (if not behind firewall)

Getting Your Token

The API requires Bearer token authentication:
# Display your current token
surge token
The token is automatically generated on first run and persists across sessions.

Base URL

The API base URL depends on your configuration:
  • Local server: http://127.0.0.1:1700
  • Custom port: http://127.0.0.1:<port>
  • Remote server: http://<server-ip>:1700
All API requests require authentication via the Authorization header:
Authorization: Bearer <your-token>

API Endpoints

Health Check

Check if the API server is running.
GET /health
{
  "status": "ok",
  "port": 1700
}
The /health endpoint does not require authentication.

Add Download

Queue a new download.
POST /download
Content-Type: application/json
Authorization: Bearer <token>

{
  "url": "https://example.com/file.zip",
  "mirrors": [
    "https://example.com/file.zip",
    "https://mirror1.com/file.zip"
  ],
  "path": "/custom/output/path"
}
Request Body
FieldTypeRequiredDescription
urlstringYesPrimary download URL
mirrorsarrayNoList of mirror URLs (includes primary)
pathstringNoCustom output directory

List Downloads

Get all downloads and their status.
GET /list
Authorization: Bearer <token>
[
  {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "url": "https://example.com/file.zip",
    "filename": "file.zip",
    "status": "downloading",
    "progress": 45.2,
    "total_size": 1073741824,
    "downloaded": 485395865,
    "speed": 12.5,
    "error": ""
  }
]

Get Download Details

Retrieve detailed information for a specific download.
GET /download?id=<download-id>
Authorization: Bearer <token>

Pause Download

Pause an active download.
POST /pause?id=<download-id>
Authorization: Bearer <token>
{
  "status": "paused",
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Resume Download

Resume a paused download.
POST /resume?id=<download-id>
Authorization: Bearer <token>
{
  "status": "resumed",
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Delete Download

Remove a download from the queue.
DELETE /delete?id=<download-id>
Authorization: Bearer <token>

# Also accepts POST
POST /delete?id=<download-id>
{
  "status": "deleted",
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Update Download URL

Update the source URL for a paused or errored download.
PUT /update-url?id=<download-id>
Content-Type: application/json
Authorization: Bearer <token>

{
  "url": "https://new-mirror.example.com/file.zip"
}
{
  "status": "updated",
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "url": "https://new-mirror.example.com/file.zip"
}
This endpoint is perfect for refreshing expired signed URLs from services like S3, Google Drive, or OneDrive.

Download History

Retrieve completed and past downloads.
GET /history
Authorization: Bearer <token>

Real-time Events (SSE)

Stream download events in real-time using Server-Sent Events.
GET /events
Authorization: Bearer <token>
The /events endpoint streams real-time updates for all download state changes, progress updates, and completions.

Response Codes

CodeDescription
200 OKRequest successful
202 AcceptedDownload queued successfully
400 Bad RequestInvalid request (missing parameters)
401 UnauthorizedInvalid or missing token
404 Not FoundDownload ID not found
405 Method Not AllowedWrong HTTP method
500 Internal Server ErrorServer error

Download Status Values

Downloads can have the following status values:
  • pending - Queued, waiting to start
  • downloading - Actively downloading
  • paused - Manually paused
  • completed - Download finished successfully
  • error - Download failed (see error field)

Integration Examples

Python Download Manager

import requests
import time

class SurgeClient:
    def __init__(self, host="http://localhost:1700", token=None):
        self.host = host.rstrip('/')
        self.token = token
    
    def _headers(self):
        headers = {"Content-Type": "application/json"}
        if self.token:
            headers["Authorization"] = f"Bearer {self.token}"
        return headers
    
    def add_download(self, url, mirrors=None, path=None):
        data = {"url": url}
        if mirrors:
            data["mirrors"] = mirrors
        if path:
            data["path"] = path
        
        response = requests.post(
            f"{self.host}/download",
            headers=self._headers(),
            json=data
        )
        return response.json()
    
    def list_downloads(self):
        response = requests.get(
            f"{self.host}/list",
            headers=self._headers()
        )
        return response.json()
    
    def pause(self, download_id):
        response = requests.post(
            f"{self.host}/pause?id={download_id}",
            headers=self._headers()
        )
        return response.json()
    
    def resume(self, download_id):
        response = requests.post(
            f"{self.host}/resume?id={download_id}",
            headers=self._headers()
        )
        return response.json()

# Usage
client = SurgeClient(token="your-token")

# Add download
client.add_download("https://example.com/file.zip")

# Monitor progress
while True:
    downloads = client.list_downloads()
    active = [d for d in downloads if d['status'] == 'downloading']
    
    if not active:
        break
    
    for d in active:
        print(f"{d['filename']}: {d['progress']:.1f}% @ {d['speed']:.1f} MB/s")
    
    time.sleep(2)

Node.js Web Dashboard

const express = require('express');
const axios = require('axios');

const app = express();
const SURGE_API = 'http://localhost:1700';
const SURGE_TOKEN = 'your-token';

const headers = {
  'Authorization': `Bearer ${SURGE_TOKEN}`,
  'Content-Type': 'application/json'
};

// Add download endpoint
app.post('/api/download', async (req, res) => {
  try {
    const response = await axios.post(
      `${SURGE_API}/download`,
      req.body,
      { headers }
    );
    res.json(response.data);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// List downloads endpoint
app.get('/api/downloads', async (req, res) => {
  try {
    const response = await axios.get(
      `${SURGE_API}/list`,
      { headers }
    );
    res.json(response.data);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.listen(3000, () => {
  console.log('Dashboard running on http://localhost:3000');
});
For production deployments, consider:
  • Using HTTPS with a reverse proxy (nginx, Caddy)
  • Implementing rate limiting
  • Adding request validation
  • Storing tokens securely (environment variables, secret managers)