Quick start
The Glitchmug API is a JSON REST API at https://api.glitchmug.com/v1 (the same API is also served at https://glitchmug.com/api/v1, which the site uses). The website is just its first client: everything you see there, you can read here.
- Reading published mods, games, users and collections needs no key.
- Writing (creating mods, uploading files, commenting, webhooks) needs an API key.
1. Check the API is up
- curl
- TypeScript
- Python
#!/usr/bin/env bash
set -euo pipefail
BASE_URL="${GLITCHMUG_API:-https://api.glitchmug.com/v1}"
curl -fsS "$BASE_URL/health"
const baseUrl = process.env.GLITCHMUG_API ?? 'https://api.glitchmug.com/v1';
const res = await fetch(`${baseUrl}/health`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
console.log(await res.json());
import json
import os
import urllib.request
base_url = os.environ.get("GLITCHMUG_API", "https://api.glitchmug.com/v1")
with urllib.request.urlopen(f"{base_url}/health") as res:
print(json.load(res))
2. List mods
Lists are filtered with query parameters and paged with a cursor. See Pagination & filters.
- curl
- TypeScript
- Python
#!/usr/bin/env bash
set -euo pipefail
BASE_URL="${GLITCHMUG_API:-https://api.glitchmug.com/v1}"
# First page; pass page.nextCursor back as ?cursor= for the next one
curl -fsS "$BASE_URL/mods?game=deadlock&sort=downloads&limit=5"
const baseUrl = process.env.GLITCHMUG_API ?? 'https://api.glitchmug.com/v1';
type Page = { data: { id: string; title: string }[]; page: { nextCursor: string | null; hasMore: boolean } };
// Walk every page of a filtered list (stop after 3 pages here)
let cursor: string | null = null;
for (let i = 0; i < 3; i++) {
const q = new URLSearchParams({ game: 'deadlock', sort: 'downloads', limit: '5' });
if (cursor) q.set('cursor', cursor);
const res = await fetch(`${baseUrl}/mods?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
const body = (await res.json()) as Page;
for (const m of body.data) console.log(m.id, m.title);
if (!body.page.hasMore) break;
cursor = body.page.nextCursor;
}
import json
import os
import urllib.parse
import urllib.request
base_url = os.environ.get("GLITCHMUG_API", "https://api.glitchmug.com/v1")
# Walk every page of a filtered list (stop after 3 pages here)
cursor = None
for _ in range(3):
query = {"game": "deadlock", "sort": "downloads", "limit": 5}
if cursor:
query["cursor"] = cursor
with urllib.request.urlopen(f"{base_url}/mods?{urllib.parse.urlencode(query)}") as res:
body = json.load(res)
for mod in body["data"]:
print(mod["id"], mod["title"])
if not body["page"]["hasMore"]:
break
cursor = body["page"]["nextCursor"]
3. Create an API key
Sign in on glitchmug.com, open Settings → API keys and create a key. The secret is shown once. Export it:
export GLITCHMUG_TOKEN=gm_xxxxxxxx_yyyyyyyy
4. Call an authenticated endpoint
- curl
- TypeScript
- Python
#!/usr/bin/env bash
set -euo pipefail
BASE_URL="${GLITCHMUG_API:-https://api.glitchmug.com/v1}"
curl -fsS "$BASE_URL/me" \
-H "Authorization: Bearer $GLITCHMUG_TOKEN"
const baseUrl = process.env.GLITCHMUG_API ?? 'https://api.glitchmug.com/v1';
const res = await fetch(`${baseUrl}/me`, {
headers: { Authorization: `Bearer ${process.env.GLITCHMUG_TOKEN}` },
});
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
const me = await res.json();
console.log(me.username, me.permissions);
import json
import os
import urllib.request
base_url = os.environ.get("GLITCHMUG_API", "https://api.glitchmug.com/v1")
req = urllib.request.Request(
f"{base_url}/me",
headers={"Authorization": f"Bearer {os.environ['GLITCHMUG_TOKEN']}"},
)
with urllib.request.urlopen(req) as res:
me = json.load(res)
print(me["username"], me["permissions"])
Next
- Uploading a mod — the whole flow, from draft to published.
- Webhooks — get told when something happens instead of polling.
- API Reference — every endpoint and schema.