Skip to main content

Uploading a mod

The same steps the website's upload form takes. Your key needs mods:write and files:upload.

draft mod ─► details, license, AI usage ─► version ─► upload files (tus) ─► release version ─► scan ─► submit mod

1. Create a draft​

POST /mods with game, category and title (slugs come from GET /games and GET /games/{slug}/categories). Send an Idempotency-Key so a retry after a timeout doesn't create a second draft.

#!/usr/bin/env bash
set -euo pipefail
BASE_URL="${GLITCHMUG_API:-https://api.glitchmug.com/v1}"

# Needs scope mods:write. Retrying with the same Idempotency-Key returns the same draft.
curl -fsS -X POST "$BASE_URL/mods" \
-H "Authorization: Bearer $GLITCHMUG_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid 2>/dev/null || echo "create-$(date +%s)")" \
-d '{"game": "deadlock", "category": "skins", "title": "Neon Haze skin"}'

The response holds the mod id you use below. Drafts are visible only to you.

2. Fill in the details​

  • PATCH /mods/{id} — summary (required to submit), description (Markdown), tags, isNsfw, contentFlags, isWip…
  • PUT /mods/{id}/license — the permissions checklist (download, redistribute, modify, reuse, commercial…), all items at once.
  • PUT /mods/{id}/ai-usage — whether AI was used for art, code, audio, text and concept.

Both PUTs are required before you can submit.

3. Create a version​

POST /mods/{id}/versions with version (e.g. 1.0.0) and an optional changelog. Supports Idempotency-Key too.

4. Upload files​

Uploads speak tus 1.0 (core, creation, termination, expiration), so any tus client works — tus-js-client, tus-py-client — with the endpoint https://api.glitchmug.com/v1/versions/{versionId}/uploads and your Authorization header.

By hand:

POST /versions/{versionId}/uploads
Tus-Resumable: 1.0.0
Upload-Length: 52428800
Upload-Metadata: filename ZHJhZ29uLXNraW4uemlw

→ 201 Created
Location: /api/v1/uploads/{uploadId}
PATCH /uploads/{uploadId}
Tus-Resumable: 1.0.0
Upload-Offset: 0
Content-Type: application/offset+octet-stream

<up to 16 MB of bytes>

→ 204 No Content
Upload-Offset: 16777216
  • Send chunks of at most 16 MB until Upload-Offset equals Upload-Length.
  • Lost the connection? HEAD /uploads/{uploadId} returns the offset to resume from.
  • DELETE /uploads/{uploadId} aborts. Unfinished uploads expire.
  • GET /uploads/{uploadId} (JSON, not tus) gives the fileId once complete.

Limits: files up to 500 MB (2 GB for trusted authors), storage quota 10 GB (50 GB trusted), 10 upload sessions per hour. Over the limit → 413 file_too_large / quota_exceeded, 429.

5. Release the version​

POST /versions/{versionId}/submit. The version goes to processing while every file is checked: antivirus scan, archive listing, unpacked size. Then it is:

  • published — when the mod is already public and the game has no premoderation (or you may publish directly);
  • pending — waiting for a moderator;
  • back to draft — if no file passed, or a check could not finish. Refused files (infected, rejected) are never served; the version is released with the clean ones.

Watch it with GET /versions/{versionId}/files: each file has scanStatus (pending, scanning, clean, infected, rejected, failed) and, when refused, scanDetail (e.g. unpack_too_large). Or subscribe to the version.published webhook.

6. Add images​

POST /images as multipart/form-data: file (jpeg, png, webp or gif, up to 10 MB), ownerType=mod, ownerId={modId}, kind=cover or screenshot, optional caption and sort. The answer is 202 with status pending; the image is ready a few seconds later. Up to 20 screenshots per mod; a new cover replaces the old one.

7. Submit the mod​

POST /mods/{id}/submit once the mod has a summary, license, AI usage and a released version with clean files. It becomes published or pending (premoderation), like versions. A rejection comes with the rule it broke; fix the mod and submit again.

Later updates: create a new version (step 3–5). The mod stays public; its current version switches when the new one is published.