Загрузка мода
Те же шаги, что проходит форма загрузки на сайте. Ключу нужны mods:write и files:upload.
черновик ─► описание, лицензия, ИИ ─► версия ─► загрузка файлов (tus) ─► выпуск версии ─► проверка ─► отправка мода
1. Создать черновик
POST /mods с game, category и title (slug-и берутся из GET /games и GET /games/{slug}/categories). Передавайте Idempotency-Key, чтобы повтор после таймаута не создал второй черновик.
- curl
- TypeScript
- Python
#!/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"}'
const baseUrl = process.env.GLITCHMUG_API ?? 'https://api.glitchmug.com/v1';
// Needs scope mods:write. Retrying with the same Idempotency-Key returns the same draft.
const res = await fetch(`${baseUrl}/mods`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.GLITCHMUG_TOKEN}`,
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({ game: 'deadlock', category: 'skins', title: 'Neon Haze skin' }),
});
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
const mod = await res.json();
console.log('draft', mod.id, mod.status);
import json
import os
import urllib.request
import uuid
base_url = os.environ.get("GLITCHMUG_API", "https://api.glitchmug.com/v1")
# Needs scope mods:write. Retrying with the same Idempotency-Key returns the same draft.
req = urllib.request.Request(
f"{base_url}/mods",
method="POST",
data=json.dumps({"game": "deadlock", "category": "skins", "title": "Neon Haze skin"}).encode(),
headers={
"Authorization": f"Bearer {os.environ['GLITCHMUG_TOKEN']}",
"Content-Type": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
},
)
with urllib.request.urlopen(req) as res:
mod = json.load(res)
print("draft", mod["id"], mod["status"])
В ответе — id мода, он нужен дальше. Черновик видите только вы.
2. Заполнить карточку
PATCH /mods/{id}—summary(обязательно для отправки),description(Markdown),tags,isNsfw,contentFlags,isWip…PUT /mods/{id}/license— разрешения (скачивание, распространение, изменение, переиспользование, коммерция…), все пункты сразу.PUT /mods/{id}/ai-usage— использовался ли ИИ для графики, кода, звука, текста и идеи.
Оба PUT обязательны перед отправкой.
3. Создать версию
POST /mods/{id}/versions с version (например, 1.0.0) и необязательным changelog. Тоже поддерживает Idempotency-Key.
4. Загрузить файлы
Загрузка работает по протоколу tus 1.0 (core, creation, termination, expiration), поэтому подойдёт любой tus-клиент — tus-js-client, tus-py-client — с адресом https://api.glitchmug.com/v1/versions/{versionId}/uploads и вашим заголовком Authorization.
Вручную:
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
<до 16 МБ данных>
→ 204 No Content
Upload-Offset: 16777216
- Отправляйте части не больше 16 МБ, пока
Upload-Offsetне станет равенUpload-Length. - Связь оборвалась?
HEAD /uploads/{uploadId}вернёт смещение, с которого продолжить. DELETE /uploads/{uploadId}отменяет загрузку. Незаконченные загрузки истекают.GET /uploads/{uploadId}(JSON, не часть tus) после завершения отдаётfileId.
Лимиты: файл до 500 МБ (2 ГБ для доверенных авторов), квота хранилища 10 ГБ (50 ГБ у доверенных), 10 сессий загрузки в час. При превышении — 413 file_too_large / quota_exceeded, 429.
5. Выпустить версию
POST /versions/{versionId}/submit. Версия переходит в processing, пока каждый файл проверяется: антивирус, список файлов в архиве, размер после распаковки. Затем она становится:
published— если мод уже публичный и в игре нет премодерации (или у вас есть право публиковать сразу);pending— ждёт модератора;- снова
draft— если ни один файл не прошёл или проверку не удалось закончить. Отклонённые файлы (infected,rejected) никогда не раздаются; версия выходит с чистыми.
Следить можно через GET /versions/{versionId}/files: у каждого файла есть scanStatus (pending, scanning, clean, infected, rejected, failed), а при отказе — scanDetail (например, unpack_too_large). Или подпишитесь на вебхук version.published.
6. Добавить картинки
POST /images в формате multipart/form-data: file (jpeg, png, webp или gif, до 10 МБ), ownerType=mod, ownerId={modId}, kind=cover или screenshot, по желанию caption и sort. Ответ — 202 со статусом pending; через несколько секунд картинка готова. До 20 скриншотов на мод; новая обложка заменяет старую.
7. Отправить мод
POST /mods/{id}/submit, когда у мода есть описание, лицензия, раскрытие ИИ и выпущенная версия с чистыми файлами. Мод становится published или pending (премодерация), как и версии. Отказ приходит с нарушенным правилом; исправьте мод и отправьте снова.
Обновления потом: новая версия (шаги 3–5). Мод остаётся публичным, текущая версия сменится, когда новая будет опубликована.