Startseite/Projekt/API

Moddingflow API

Bereiche

Mod Manager Installation und Download

8

1. Suche anonym mit gewöhnlichem curl: curl "https://moddingflow.com/v1/search?q=skyui&game=skyrim-se". 2. Lies das ausgewählte Artifact mit GET https://moddingflow.com/v1/artifacts/{artifact_id} und bestätige lokales Spiel und Profil. 3. Löse mit POST https://moddingflow.com/v1/install-plans:resolve einen Installationsplan auf. 4. Rufe POST https://moddingflow.com/v1/downloads/{artifact_id}/resolve erst nach der Bestätigung auf. 5. Prüfe hashes.sha256. Für einen öffentlichen Mod sind weder Konto, API-Schlüssel, OAuth-Registrierung, Bearer-Token, spezieller User-Agent noch X-Moddingflow-Header nötig. URLs mit und ohne abschließenden Slash werden direkt ohne 308 bedient. TypeScript-, Python- und C#-SDKs funktionieren ohne accessToken. Liefert account-scoped Content 401/403, schließe OAuth ab und wiederhole mit einem Bearer Token. Behandle 429, 5xx, abgelaufene signierte URLs und falsche Hashes mit Backoff und einer neuen Resolve-Antwort.

/403https://moddingflow.com/v1/install-plans:resolvehttps://moddingflow.com/v1/artifacts/{artifact_id}https://moddingflow.com/v1/search?q=skyui&game=skyrim-se"https://moddingflow.com/v1/downloads/{artifact_id}/resolve

Die Website übergibt dem Betriebssystem ausschließlich den kanonischen URI moddingflow://download?v=1&artifact_id=<uuid>. Dieses neutrale Protokoll kann jeder Mod Manager unterstützen; die Standard-App wählt der Nutzer. Akzeptiere nur die exakte Version v=1 und eine kanonische artifact_id-UUID. Lehne unbekannte Versionen, zusätzliche oder doppelte Parameter, fehlerhafte UUIDs, HTTP-URLs, Signed URLs, OAuth-Codes, Tokens, API-Schlüssel, Website-Sessions und jedes andere Secret ab. Ein fehlgeschlagenes Handoff darf nie zum Browser-Download werden.

Nach Cold-, Warm- oder Second-Instance-Aktivierung legt ein strikter Parser genau eine normalisierte artifact_id in der Activation Inbox ab. Danach ruft der Manager GET /v1/artifacts/{artifact_id} auf, zeigt eine lokale Bestätigung für Spiel, Profil und Instanz, bezieht den Plan über POST /v1/install-plans:resolve und ruft POST /v1/downloads/{artifact_id}/resolve erst nach ausdrücklicher Bestätigung auf. Der Empfang des URI darf weder Download noch Installation automatisch starten. Die Website erfasst manager_handoff_attempt separat; ein Manager-Download zählt erst nach erfolgreicher API Download-Job-Aktivierung.

POST /v1/install-plans:resolveGET /v1/artifacts/{artifact_id}POST /v1/downloads/{artifact_id}/resolvev=1//download

Fordere Artifact-Metadaten, Installationsplan und Download-Auflösung zuerst anonym an. Liefert account-scoped Content 401/403, starte OAuth und wiederhole mit einem Bearer Access Token. Ein nativer Manager ist ein Public Client und nutzt Authorization Code + PKCE S256 im Systembrowser mit einem exakten Loopback Redirect URI wie http://127.0.0.1:<port>/oauth/callback. Verwende weder einen gemeinsamen Personal API Key noch client_secret, Embedded WebView, Implicit Flow oder Password Grant und übertrage Code oder Token nie durch moddingflow://. Refresh Tokens gehören ausschließlich in geschützten Credential Storage.

Fluxora verwendet weiterhin den Public Client desktop_mod_manager. Jeder Drittanbieter-Manager registriert einen eigenen Public OAuth Client und Redirect URI und implementiert den strikten Protocol-v1-Parser, serverseitige Artifact-Revalidierung, lokale Bestätigung und den API Download-Job-Lifecycle. client_id, Personal API Key oder Secret dürfen nicht zwischen Managern geteilt werden. Unter Windows registriert ein Manager seine eigene moddingflow-Capability, übernimmt keinen fremden Default Handler und öffnet den System-App-Picker, wenn der Handler gewechselt werden soll.

///403http://127.0.0.1:<port>/oauth/callback

Rufe GET https://moddingflow.com/v1/artifacts/{artifact_id} auf, wenn ein App-Handoff nur eine stabile Artefakt-UUID enthält. Der Endpoint liefert eine private/no-store Allowlist mit Spiel, Mod, exakter Version, veröffentlichtem sauberen Artefakt, SHA-256, Größe, permanenten Moddingflow-Links und dem stabilen Download-Resolve-Endpoint. Er erstellt oder setzt keinen Download-Job fort, erzeugt keinen Grant und gibt weder Signed URL noch ETag, Storage Key, Uploader-E-Mail oder internes Entitlement-Feld zurück. Öffentliche Artefakte funktionieren anonym; wenn ein Bearer-Token gesendet wird, muss es mods:read enthalten, und ungültige Credentials fallen nie auf anonymen Zugriff zurück. Lass den Nutzer das lokale Spiel/Profil bestätigen, bevor Download Resolve aufgerufen wird.

/Profil/no-storemods:readhttps://moddingflow.com/v1/artifacts/{artifact_id}

Nutze POST /v1/install-plans:resolve, um ausgewählte mods, versions oder artifacts in einen deterministischen plan umzuwandeln. Sende game_slug, game_version, platform, loader, release_channel und mindestens einen stabilen selector. Die Response ergänzt typed dependency_constraints, conflicts, artifact_selection, decision_reasons, stabile plan_id und item_id Werte und behält legacy dependency und step fields. Required und optional dependencies, conflicts und embedded contents sind maschinenlesbar; embedded content erzeugt keinen separaten download, optionale artifacts benötigen include_optional=true. Neue Clients behandeln hashes.sha256 als canonical und können sha256 als compatibility alias lesen; beide Felder decken die vollständigen unveränderlichen gespeicherten Objektbytes ab und werden nach dem Vergleich von size_bytes geprüft. Rufe danach POST /v1/downloads/{artifact_id}/resolve für jedes artifact auf und installiere erst nach erfolgreicher SHA-256 Prüfung des vollständigen Archivs. Bestehende legacy public file URLs bleiben während der Migration derselben artifact identity zugeordnet und erfordern keinen erneuten archive upload.

Die manuelle Sicherheitsprüfung fügt in v1 weder ein öffentliches Feld noch einen neuen Error Code hinzu. Ein Artifact im Status Wird geprüft nutzt den normalen Resolve-Ablauf; ein unsicheres Artifact wird fail-closed über den bereits dokumentierten generischen 404/unavailable Contract abgewiesen und erhält keine Signed URL. Clients dürfen diesen Fall nicht von anderer Artifact-Nichtverfügbarkeit unterscheiden.

Ein erfolgreicher POST https://moddingflow.com/v1/downloads/{artifact_id}/resolve liefert denselben vollständigen mod: PublicMod Snapshot wie der GET-Katalog, die exakt ausgewählte version und das heruntergeladene artifact sowie distribution.service=moddingflow mit permanenten website_url, mod_url und api_url Werten. Die ausgewählte version kann von mod.latest_release abweichen und darf vom Client nicht durch die neueste ersetzt werden. primary_url und expires_at beschreiben eine temporäre direkte Signed URL; nach Ablauf wird der stabile download_grant.resolve_endpoint erneut aufgerufen (auch in resume.signed_url_expiry_refresh gespiegelt). primary_url darf weder gespeichert noch als Ersatz für permanente links.web, source_url oder homepage_url verwendet werden.

POST /v1/install-plans:resolvePOST /v1/downloads/{artifact_id}/resolve/unavailableoptional=trueservice=moddingflowhttps://moddingflow.com/v1/downloads/{artifact_id}/resolve

Wenn Resolve artifact_source=external_provider_reference liefert, behandle transport als discriminated union und nicht als managed CDN URL. transport.kind ist external_provider_reference und enthält provider, reference_id, reference_revision, eine kurzlebige url, expires_at und ttl_seconds; die Response enthält außerdem exakte size_bytes, hashes.sha256 und wahrheitsgemäße capabilities. Die URL ist keine Identity, darf weder dauerhaft gespeichert noch geloggt werden und wird durch einen erneuten Aufruf des stabilen POST /v1/downloads/{artifact_id}/resolve aktualisiert.

Beachte head_supported und range_supported. Wenn conditional_requests=false gilt, ist conditional_headers leer, ETag/if_match sind null und der Client darf If-Match nicht erfinden. Setze nur bei range_supported=true und unverändertem SHA-256 fort und vergleiche nach dem Zusammensetzen size_bytes und den SHA-256 der vollständigen Datei. Für externen Transport gilt fallback.available=false und Fallback-Endpoints sowie URLs sind null: Rufe keinen Bunny/R2-Fallback auf, öffne keinen Browser und starte aus dem Manager-Modus keinen separaten Direct-HTTP-Pfad. Source-gehostete Bytes zählen nicht als Moddingflow-Egress.

Resolve ist nur für eine aktive verified Reference mit frischer Server-Attestation verfügbar. reference_pending und reference_stale bedeuten, auf die Validierung zu warten; reference_withdrawn und hash_mismatch bedeuten, die Installation abzubrechen; provider_rate_limited und provider_unavailable dürfen nur gemäß Retry-Guidance wiederholt werden. Entfernte oder geänderte Bytes blockieren die alte Version, eine geänderte Datei benötigt eine neue Version. artifact_source=rehosted_blob behält die bestehenden managed Session-, HEAD-, Range- und Fallback-Semantics unverändert.

POST /v1/downloads/{artifact_id}/resolve/if_match/R2-Fallbackrequests=falsesupported=trueavailable=falsesource=rehosted_blobsource=external_provider_reference

Für ein managed artifact_source=rehosted_blob erstellt oder setzt Download Resolve einen actor-gebundenen dauerhaften download job mit einem stabilen kurzlebigen grant fort und liefert nach erfolgreicher Grant-Aktivierung 200 JSON; er verwendet keinen 302 redirect und streamt keine binary data. Speichere artifact_id, download_job.id, download_job.grant_id und download_session_id, nicht primary_url, head_url oder fallback_url. primary_url ist für GET mit Range und If-Match/If-None-Match/If-Modified-Since/If-Unmodified-Since; die separat signierte head_url ist für HEAD mit Content-Length und ETag. Nutze expires_at, expires_in und refresh_after_seconds, um POST /v1/downloads/{artifact_id}/resolve erneut aufzurufen, dieselben hashes.sha256/sha256 und size_bytes zu prüfen und nach URL-Ablauf ab dem letzten dauerhaften Byte fortzusetzen. Fallback nutzt POST /v1/downloads/{artifact_id}/fallback mit downloadSessionId und erzeugt nur dann eine weitere signed URL, solange der grant aktiv ist.

hashes.sha256 und der legacy sha256 alias sind der application-level SHA-256 der vollständigen unveränderlichen gespeicherten Objektbytes. Nach normalem HTTP decoding muss der Client das vollständige Objekt aus allen Range-Teilen in Byte-Reihenfolge zusammensetzen, size_bytes vergleichen und erst dann den Digest prüfen; eine einzelne 206 response wird durch diesen full-file hash nicht separat verifiziert. ETag ist kein kryptografischer Digest, sondern ein opaque Validator für genau eine transport representation. Lies representation.provider, etag_scope, etag und if_match und sende If-Match nur, wenn representation.provider mit etag_scope übereinstimmt. Nach provider failover liefert fallback absichtlich etag=null, if_match=null und requires_head_before_range=true: führe zuerst HEAD für die fallback representation aus und verwende nur den neuen ETag dieses provider. Signed transports müssen stored bytes ohne transcoding erhalten; der aktuelle Vertrag garantiert RFC 9530 Content-Digest oder Repr-Digest nicht, daher nutzen Clients die response-body hash fields.

Vor URL signing wird der access tier fail-closed geprüft: public erlaubt anonymous download, authenticated verlangt einen actor, paid ein active subscriber entitlement und restricted einen active artifact/mod resource grant; ein expired oder revoked entitlement liefert 403 ohne signed URL. Der Zugriff ist außerdem durch client/app identity, files:download oder delegated download scope, route rate limits und byte budgets begrenzt. 404 bedeutet unavailable artifact, 401/403 auth- oder entitlement-Problem, 429 backoff, und 410 oder download_session_expired einen abgelaufenen oder nicht mehr nutzbaren grant. Bei 429 beachtet der Client Retry-After, speichert den sicheren download_job aus Problem Details und wiederholt mit job_id, monotonem progress.bytes_received, progress.provider und passendem ETag; wiederholte Limits behalten denselben Job und Grant ohne erneute Provider-Arbeit. Signed URL hosts, provider names und query strings sind opaque transport details und können sich ändern, ohne stabile Clients zu brechen.

POST /v1/downloads/{artifact_id}/resolvePOST /v1/downloads/{artifact_id}/fallback/mod/app/403/sha256etag=nullmatch=nullrange=truefiles:downloadsource=rehosted_blob/If-None-Match/If-Modified-Since/If-Unmodified-Since

Behandle 400 und 422 als Request-Fehler, 401 oder 403 als auth/scope Problem, 404 oder 410 als stale selection, 409 als Konflikt für erneute Planung, 429 als backoff Signal und 5xx als retryable mit jitter. Errors verwenden RFC 9457 Problem Details mit application/problem+json: verzweige nach type oder code, niemals nach lokalisiertem detail. Jeder runtime error enthält retryable und docs_slug. retry_after_seconds und quota_bucket erscheinen nur bei sicherer retry- oder quota guidance, required_scopes nur wenn diese scopes die Autorisierung bestehen lassen, und fields nur für sichere validation details. Die OpenAPI x-moddingflow-error-registry ist die source of truth und entwickelt sich innerhalb von v1 nur additiv; bewahre unbekannte zukünftige codes und nutze den numerischen status als fallback. Typed SDK errors behalten diese Felder im parsed payload zusammen mit headers, request_id und trace_id. Bei 429 warte mindestens Retry-After Sekunden und lies RateLimit-Limit, RateLimit-Remaining und RateLimit-Reset vor jittered exponential backoff. Verwende einen stabilen Idempotency-Key pro logischer write oder deterministic resolve retry; 409 idempotency_conflict bedeutet, denselben body erneut zu senden oder eine neue Operation mit neuem key zu starten. Bewahre X-Request-Id, request_id und trace_id für support logs auf.

Bei external references verlangen provider_unsupported (400) und locator_invalid (422) einen korrigierten Request; source_already_imported (409) bedeutet, die bestehende Reference zu verwenden. reference_pending und reference_stale (409) sperren Resolve bis zur erfolgreichen Server-Validierung, reference_withdrawn (410) und hash_mismatch verbieten die Installation, und fallback_unavailable (409) bestätigt, dass kein managed Mirror existiert. provider_rate_limited (429) beachtet Retry-After, provider_unavailable (503) nutzt Backoff. Umgehe diese Fehler nie mit einer gespeicherten Provider-URL; fordere erst dann einen neuen Resolve an, wenn die Reference wieder verified und fresh ist.

/scope/problemIdempotency-Key

Creator Upload und Publish Automation

7

Das primäre Upload API target ist ein Creator, der ein mod archive lokal oder in CI baut und danach eine new version für einen existing mod veröffentlicht, ohne die browser form zu öffnen. Derselbe Pfad muss für GitHub release oder tag pipelines passen: build archive, run local checks, version draft erstellen oder wiederverwenden, upload direct-to-storage, scan und validation abwarten und erst publish ausführen, wenn die API ready meldet.

Team publishing nutzt individual API keys, OAuth apps oder PATs mit den kleinsten verfügbaren scopes, damit maintainers niemals owner password oder main account session teilen. Tool integrations sollen einen Publish to Moddingflow Button in launcher, editor oder build tool platzieren können und trotzdem denselben machine-readable upload status, request_id und trace_id anzeigen, den CI sieht.

Failure states gehören zum product contract: upload_interrupted hält den upload resumable oder abortable, scan_failed und validation_failed blockieren publish mit Details, permission_denied nennt den fehlenden scope oder project access, quota_exceeded gibt retry guidance zurück, und duplicate_version fordert den Client auf, die version wiederzuverwenden oder zu ändern. Verdächtige Dateien wechseln nach quarantine/review; clients erhalten einen clear status statt silent failure. Das public promise ist sicherere automation als die manual form: direct cloud upload, least-privilege keys, no shared owner credentials, auditable provenance und security checks, bevor eine Datei users erreicht.

/review

Wenn der Rollout aktiviert ist, registriere eine externe Datei mit POST /v1/mods/{mod_id}/versions/{version_id}/external-artifact und einem verpflichtenden Idempotency-Key. Sende einen discriminated provider locator, expected_size_bytes, erwartete Hashes, content_type, canonical evidence und provenance, niemals eine beliebige Download-URL. Ein erfolgreicher 202 liefert artifact_id, reference_id, validation_job_id, state=pending und status_resource; frage GET /v1/external-artifact-validation-jobs/{validation_job_id} ab. Derselbe Key mit demselben Body liefert das ursprüngliche Ergebnis, derselbe Key mit anderem Body 409 idempotency_conflict.

Die aktuelle Registry akzeptiert nur kanonische Locators für GitHub, Modrinth, Hangar und Codeberg. Ein beliebiger Provider liefert provider_unsupported, ein instabiler Locator locator_invalid. Eine Provider- oder Signed URL ist niemals Identity und wird weder in Datenbank noch Logs gespeichert. Die Eindeutigkeit des Provider-Locators verhindert doppelte Imports; Hashes dienen dem Server-Scan-Cache, ersetzen aber nicht die Identity. Modrinth verlangt SHA-512, SHA-1 und einen lokal berechneten SHA-256; für jeden Provider sind exakte Größe und SHA-256 erforderlich.

files:reference ist ein sensibler review_required Scope: Seine Vergabe verlangt AAL2, ausdrücklichen Consent, einen genehmigten Client- oder Credential-Pfad und die Rolle owner, maintainer oder publisher am Mod. Die Registrierung ist auf öffentliche, kostenlose Mods beschränkt. Die unabhängigen Flags registration_enabled, worker_enabled und resolve_enabled sind standardmäßig false. Auch die vier Provider-Gates github_enabled, modrinth_enabled, hangar_enabled und codeberg_enabled sind unabhängig und standardmäßig aus; der gewählte Provider muss für Registrierung, Worker Claim, Revalidierung, Manager View und Resolve aktiviert sein. Erfolgreiche Registrierung bedeutet nicht, dass Resolve aktiv ist. Der Worker ist authoritative: Er lädt Provider-Metadaten und Bytes selbst, prüft Hash, Größe, Archiv und Security Policy und schreibt eine unveränderliche Attestation; Importer-Evidence bleibt advisory.

GET /v1/external-artifact-validation-jobs/{validation_job_id}POST /v1/mods/{mod_id}/versions/{version_id}/external-artifactstate=pendingIdempotency-Keyfiles:reference

Beginne mit dem validate-only endpoint POST /v1/uploads:validate; er prüft sizeBytes, expectedHashes.sha256, archiveManifest und buildMetadata, ohne eine Session, ein storage object oder einen audit write zu erstellen. Creator automation öffnet danach POST /v1/uploads, sendet archive bytes direkt in private Cloudflare R2 über eine signed single PUT URL oder signed multipart parts, erneuert parts mit POST /v1/uploads/{upload_id}/parts, prüft GET /v1/uploads/{upload_id}, schließt mit POST /v1/uploads/{upload_id}/complete ab und storniert mit POST /v1/uploads/{upload_id}/abort. Die Next.js API erhält nur metadata und lifecycle calls, niemals den archive body. Große multipart Sessions bleiben 48 Stunden aktiv, jede signed URL 15 Minuten. status.progress liefert uploadedBytes, percent, totalParts und provider-confirmed completedParts mit ETags, damit Website, CLI und GitHub Action nach einer Unterbrechung nur missing parts fortsetzen. Ein private staging object kann vor complete, size/content type/archive format validation und security processing nicht published werden; ein bounded cleanup job bricht expired multipart uploads ab oder löscht incomplete single objects. Complete liefert einen async job, solange scan, metadata extraction, indexing hooks oder final promotion laufen; poll job.statusEndpoint. queued und processing sind non-terminal, succeeded, rejected, failed und cancelled sind terminal. job.progress zeigt ehrlich 0/1 completion statt eines geschätzten scan percentage. createdAt, updatedAt, startedAt, completedAt, retry attempts, nextAttemptAt und der stabile terminal reason unterscheiden active, retrying und finished work, ohne provider prose offenzulegen. Kanonische lifecycleStatus Werte sind draft, uploading, uploaded, validating, scanning, quarantined, ready, published, failed und cancelled; legacy status bleibt ein compatibility alias. expectedSha256 bleibt ein legacy alias und sha256_mismatch lehnt den Upload vor promotion ab. Idempotency-Key bleibt für create und complete retries stabil. Version request metadata unterstützt version, changelog, file_category, game_slug, game_versions, loader_platforms, dependencies, requirements und build_metadata; eine wiederholte logische Version liefert duplicate_version. metadata-only edits erfordern keinen erneuten upload bytes. Der security worker claimt durable jobs atomar, wiederholt transient failures und verschiebt exhausted oder ungeprüfte uploads in quarantine. Die ZIP policy liefert archive_dangerous_entry, archive_encrypted_entry, archive_symlink_entry, archive_duplicate_path oder archive_path_traversal; nested archives werden bis Tiefe 3 rekursiv geprüft; unzulässige executable-Szenarien gelten als unsafe, während jede Datei über dem ClamAV-Streamlimit manual review erfordert.

Der isolierte archive-security-worker prüft das immutable scan seal: den vollständigen SHA-256, die ZIP/7z/RAR-Struktur und den ClamAV-Verdict. Auch die Wiederverwendung eines Exact-SHA-Clean-Cache verlangt dasselbe Format, dieselbe Policy-Version, Engine und Signaturdatenbank. Transiente Fehler erhalten höchstens drei Versuche; unbekannte Ergebnisse, veraltete Datenbanken und Ressourcenlimits werden nie clean und halten die Datei privat in Quarantäne/Prüfung.

Numerische Upload-Defaults: Single PUT bis 100 MiB; Multipart Parts mit 16 MiB und Concurrency 4; ein Signing Request enthält höchstens 4 Parts und begrenzt die Payload in Flight auf 64 MiB; ein Archiv ist auf 20 GiB begrenzt. Der authentifizierte Upload-Byte-Bucket beträgt 24 GiB. Ein Live-R2-Capacity-Probe bestätigte 64 MiB Upload/Download mit gleichem SHA-256, RSS Delta unter 384 MiB und verpflichtendem Cleanup; das Profil 64 MiB × 4 wurde wegen Überschreitung des Memory Budgets abgelehnt.

Wenn complete einen nicht terminalen Job mit Status queued oder processing erzeugt, lautet die HTTP-Antwort 202 Accepted und der Location-Header entspricht exakt job.statusEndpoint. Ist der Job bereits terminal (succeeded, rejected, failed oder cancelled), einschließlich eines idempotenten Replays dieses terminalen Ergebnisses, liefert complete 200 OK, ohne den Side Effect zu wiederholen.

Ein Replay von POST /v1/uploads mit demselben Body und Idempotency-Key liefert die ursprüngliche durable Session mit neu signierten Upload-Anweisungen. Jede single PUT URL hat höchstens eine 900-second Lease, die der Server nach dem Signing und vor der Response unter Row Lock checkpointet; ein abort-winning Checkpoint verwirft die URL-Response. Sende alle zurückgegebenen Header einschließlich If-None-Match: *. Ein conditional 412 ist ein ambiguous existing write: Überschreibe Staging nicht, sondern rufe denselben complete Endpoint auf, wo HEAD, immutable Seal und SHA-256 authoritative sind. Signed URLs und Provider-Upload-IDs werden nie im generischen Idempotency-Datensatz gespeichert; prüfe nach einem mehrdeutigen Create-Timeout zuerst die Upload-Session, bevor du eine neue Mutation startest.

Nutze für polling guidance retry.retryable, retry.strategy, retry.attempt, retry.maxAttempts, retry.nextAttemptAt und retry.retryAfterSeconds. Eine HTTP response kann dieselbe Mindestverzögerung über Retry-After angeben.

Das manuelle Mod-Upload-Formular der Website nutzt dieselben Upload-Session-Dienste und dasselbe private R2-Backend. Es zeigt Dateiübertragung und Sicherheitsprüfung, bewahrt einen erstellten Mod-Entwurf nach einer Netzwerkunterbrechung auf und verwendet vom Speicheranbieter bestätigte Multipart-Teile erneut, wenn dieselbe Datei gewählt wird. Vor dem Multipart-Commit prüft der Server die exakte Größe und den Provider-ETag/MD5 jedes Teils erneut; danach verifiziert der asynchrone Trust-Worker den SHA-256 des gesamten Objekts vor ready/publish. Unter Einstellungen > Entwickler siehst du aktuelle Sessions, Scan-Fehler sowie den Quarantäne- und Prüfstatus.

POST /v1/uploadsPOST /v1/uploads:validateGET /v1/uploads/{upload_id}POST /v1/uploads/{upload_id}/partsPOST /v1/uploads/{upload_id}/abortPOST /v1/uploads/{upload_id}/complete/1/Pr/MD5/content/archive/publish/DownloadIdempotency-Key/7z/RAR-Struktur

Wähle die manual browser form für einen gelegentlichen geführten Release. Nutze Upload API für wiederholbare local tools, CI und GitHub Actions. Beide Wege verwenden dasselbe upload-session backend, private Cloudflare R2 storage, validation, scan, quarantine/review und ready-before-publish security gates.

Gib jeder Person oder automation einen individual resource-scoped key mit den smallest required scopes. Das raw secret wird one-time angezeigt. Speichere MODDINGFLOW_API_KEY in einem GitHub environment or repository secret, niemals in workflow YAML, repository variables, logs, command arguments oder artifacts. Nutze protected environments, minimal workflow permissions und einen geprüften 40-character Action commit SHA.

Nach scan_failed oder av_scan_rejected darfst du nicht veröffentlichen oder das Archiv neu verpacken, um das verdict zu umgehen. Halte die Datei private, frage GET /v1/uploads/{upload_id} ab, notiere supportCorrelationId oder X-Upload-Correlation-Id, request_id, trace_id und error code und folge danach quarantine/review, manual review oder support guidance. Die correlation id darf mit dem support geteilt werden: Sie enthält kein secret und gewährt keinen Zugriff. Erstelle eine new session erst nach Behebung der erkannten Ursache.

Öffne die FAQ für Workflow-Entscheidungen und die API reference für Status-, Fehler- und Scope-Schemas.

GET /v1/uploads/{upload_id}/review

Game, Mod, ModVersion, Artifact, Blob, UploadSession, DownloadGrant, User, Team, Dependency, Job, WebhookSubscription und WebhookDelivery besitzen jeweils eine eigene opaque UUID, eine Ownership-Regel und eine fail-closed State Machine. Slug, Benutzername, Teamname, Dateiname, URL, Storage Key, ETag oder Hash sind keine öffentliche Identität. Speichere die zurückgegebene UUID; eine Umbenennung ändert sie nie.

Archivierung ist reversibel, eine dauerhafte Löschung erzeugt jedoch einen aufbewahrten Tombstone. Eine unbekannte UUID liefert 404; eine tombstoned UUID liefert 410 und wird nie wiederverwendet. Der kanonische Versions-Lifecycle lautet draft → validating → scanning → ready → published → archived/withdrawn; failed ist ein explizites Ergebnis. uploaded, quarantined, approved und rejected bleiben Kompatibilitäts-Aliase für alte Clients.

Bei der ersten Veröffentlichung speichert der Server einen unveränderlichen Snapshot aus Version, Dateityp, Release-Kanal, Spiel- und Loader-Bindungen, Blob-UUID, Größe und Inhaltstyp sowie dessen SHA-256. Diese Felder können danach nicht in-place geändert werden; Restore aus archived/withdrawn wird nur akzeptiert, wenn der Snapshot exakt übereinstimmt und die aktuellen Upload-Trust-Gates erneut bestehen. Öffentliche parallele Mod/ModVersion PATCH Requests verwenden einen starken ETag in If-Match: Ohne Validator folgt 428, bei einem stale validator 412 mit dem aktuellen ETag. lifecycle_version bleibt das interne optimistic lock für Lifecycle-Transitions.

/withdrawn/ModVersion

Contract 1.1 mod-media ergänzt PublicMod.cover, PublicMod.gallery und PublicModMedia additiv. GET /v1/mods/{mod_id}/media liefert projektbezogene Medien. POST /v1/mods/{mod_id}/media akzeptiert eine Multipart-Datei mit JSON-Metadaten; POST /v1/mods/{mod_id}/media:fallback erzeugt ein deterministisches Cover; DELETE /v1/mods/{mod_id}/media/{media_id} entfernt nur importer-managed media. Schreibzugriffe verwenden den vorhandenen Scope mods:write mit Idempotency-Key und starkem If-Match. Internes rights evidence bleibt aus öffentlichen Antworten ausgeschlossen; eine Veröffentlichung ohne Cover liefert cover_required.

GET /v1/mods/{mod_id}/mediaPOST /v1/mods/{mod_id}/mediaPOST /v1/mods/{mod_id}/media:fallbackDELETE /v1/mods/{mod_id}/media/{media_id}mods:writeIdempotency-Key

Publishing automation erstellt oder aktualisiert einen mod draft, erstellt einen version draft, hängt ein clean upload artifact an, validiert metadata und ruft publish erst auf, wenn der Creator bereit ist. Nutze mods:write für mod metadata und versions:write für version changes.

mods:writeversions:write

Katalog- und Suchintegrationen

3

Für catalog integrations nutze GET /v1/games, GET /v1/categories, GET /v1/mods, GET /v1/mods/{mod_id}, GET /v1/mods/{mod_id}/versions, GET /v1/mods/{mod_id}/dependencies und GET /v1/search. List und search nutzen cursor-first keyset pagination mit cursor, limit (default 25, max 100), stable tie-breaking und opaque v1 base64url cursor values; gib den cursor aus der vorherigen Response weiter und erzeuge keine offset oder page-number cursors. Jeder cursor ist an resource, normalized filters, sort und den insertion snapshot der ersten Seite gebunden. Wiederverwendung mit geändertem Kontext liefert 400 invalid_input; nach Seite eins erstellte oder veröffentlichte Zeilen bleiben außerhalb dieses cursor snapshot. GET /v1/mods und GET /v1/search akzeptieren die filters game_slug, q, sort=relevance|latest|trending|downloads, game_version, loader und category; der website compatibility namespace akzeptiert außerdem die aliases game/gameSlug, query/search, gameVersion/version, platform und facet. Search erfordert q, nutzt standardmäßig sort=relevance und verwendet denselben begrenzten RU/EN/DE query plan mit Normalisierung, Aliasen, Tastaturkorrektur, Transliteration und Tippfehlerkorrektur wie Website-Suche und Agent Gateway mods.search. Response-Schema, Pagination und Cursor-Vertrag bleiben unverändert. List ohne query verwendet standardmäßig latest. Reserved resource filters: versions: mod_id, release_channel, game_version, loader, published_after, published_before; files: mod_id, version_id, artifact_id, file_kind, status, sha256; upload sessions: status, strategy, file_id, created_after, created_before; download grants: artifact_id, status, expires_after, expires_before; webhook deliveries: event_kind, delivery_status, created_after, next_attempt_before.

Anonyme Catalog-GET-Responses verwenden Cache-Control public, einen weak ETag und Vary: Accept-Encoding, Authorization, Cookie. Sende den gespeicherten ETag als If-None-Match, um bei unveränderter Representation eine leere 304-Response zu erhalten. Ein Request mit Authorization oder Cookie ist immer private no-store und verwendet den public validator nicht, sodass authentifizierte und anonyme Responses keinen Cache-Eintrag teilen.

Beispiel für vollständige Metadaten: GET https://moddingflow.com/v1/mods?game_slug=skyrim-se-ae&limit=25 und danach GET über die absolute links.api URL. PublicMod behält summary als kurzen Excerpt, während description das ungekürzte Markdown des ersten sichtbaren Beitrags mit description_format=markdown liefert. author ist ausschließlich der Moddingflow-Uploader; bei geschlossenem Profil ist profile_url null. latest_version bleibt das Compatibility-Feld und wird aus der ersten aktiven Hauptdatei abgeleitet. latest_release enthält die autoritativen Werte id, dieselbe Dateiversion, primary_artifact_id, published_at der ersten Veröffentlichung und updated_at des Releases oder ist bei einem Legacy-Datensatz ohne bestätigte Version null. links.web ist die permanente Moddingflow-Seite, links.api und links.versions sind permanente API-URLs. homepage_url gehört dem Autor oder Projekt; source_url bleibt die vom Uploader angegebene Upstream-Seite und wird nie durch eine Moddingflow-URL ersetzt.

GET /v1/modsGET /v1/gamesGET /v1/searchGET /v1/categoriesGET /v1/mods/{mod_id}GET /v1/mods/{mod_id}/versionsGET /v1/mods/{mod_id}/dependencies/EN/DE/search/version/gameSlugsort=relevanceformat=markdownhttps://moddingflow.com/v1/mods?game_slug=skyrim-se-ae&limit=25

Public payloads verwenden stabile UUIDs für games, mods, versions, artifacts und dependencies. Verlasse dich nicht auf website forum topic IDs, storage object names oder human-readable slugs als durable integration keys.

Renames, metadata rebuilds und slug changes behalten bestehende mod, version, artifact, upload-session und download-grant identifiers. Das Ersetzen von Datei-Bytes erzeugt einen neuen physical blob und kann eine neue logical artifact/version binding erzeugen; metadata-only edits erzwingen keinen erneuten Datei-Upload durch Clients.

/version

Das stabile v1 model trennt mod, version, logical file, physical blob, upload-session, download-grant, token und webhook-delivery. Ein mod besitzt versions, eine version verweist über artifact ids auf logical files, und ein logical file kann an einen immutable physical blob im storage gebunden sein, ohne storage paths offenzulegen.

Behandle slug und localized slugs als mutable aliases, filename als display/download text und hash values wie sha256 oder hashes.sha256 als integrity checks. Speichere public ids und lifecycle ids: mod id, version id, artifact id, sessionId, download_session_id, token metadata id und webhook delivery id, sobald webhook delivery endpoints veröffentlicht sind.

PublicModVersion.artifact_ids bleibt die stabile Verknüpfung. Optional PublicModVersion.artifacts erscheint nur für ein managed primary artifact, wenn size_bytes > 0, sha256/hashes.sha256 exakt sind, die current upload session sowohl file_id als auch final_blob_id abgleicht, actual AV scan_status=clean ist, lifecycle=ready, publication state=published und managed resolve eligible ist; andernfalls wird die Erweiterung omitted. Das vollständige Objekt enthält id, mod_id, version_id, file_kind, file_version der konkreten Datei, ein non-null label, nullable original_filename, content_type, game_version_key und loader_key, danach size_bytes, sha256, hashes, artifact_source, status, scan_status und download_metadata. PublicModVersion.version entspricht artifact.file_version; PublicMod.latest_version und latest_release.version spiegeln zur Kompatibilität die Version der ersten aktiven Hauptdatei. Actual AV states sind pending, queued, scanning, clean, quarantined, rejected, failed und skipped. download_metadata enthält einen relative resolve_endpoint und einen wahrheitsgemäßen range_supported-Wert, aber nie eine provider URL.

/downloadstatus=clean/hashes.sha256lifecycle=readystate=published

Agent Gateway delegated tools

3

Die ausschließlich für die offizielle Desktop-App bestimmte Route POST /api/fluxora/ai/agent ist kein Teil des öffentlichen /v1 Agent Gateway. Sie erfordert den OAuth-Client desktop_mod_manager mit agent:run und X-Fluxora-AI-Protocol: 4, legt Provider/Modell auf OpenAI GPT-5.6 Luna fest und akzeptiert nur responses.create, responses.input_tokens oder models.retrieve. Drittclients können agent:*-Scopes weder registrieren noch diese Route als OpenAI-Proxy nutzen. Nach der v4-Aktivierung liefert die alte Gemini/v3-Route 410 ai_client_upgrade_required.

POST /api/fluxora/ai/agent/v1/Modellagent:run/v3-Routeagent:*-Scopes

Agent Gateway stellt enge tools für mods.search, mods.get, install_plans.resolve, downloads.resolve, versions.compare, publisher.draft und publisher.validate bereit. Agents sollen tools aufrufen statt Seiten zu scrapen oder arbitrary URLs zu fetchen.

Ein Agent erhält ein kurzlebiges token mit audience agent-gateway und engen tool scopes. Er bekommt nie den vollständigen user session token. Read tools können direkt laufen; write-capable tools bleiben dry-run, bis ein confirmation token die konkrete Aktion erlaubt.

Auth und URL Grenzen

2

API base URL: https://moddingflow.com/v1. OAuth issuer URL: https://moddingflow.com. API compatibility namespace: https://moddingflow.com/api/v1. Beide Namespaces akzeptieren Operation-URLs mit und ohne abschließenden Slash direkt, ohne 308. Die official CLI bietet außerdem ein local sandbox profile unter http://127.0.0.1:3000/api/v1; protected staging nutzt die vom Operator gelieferte MODDINGFLOW_STAGING_API_BASE_URL und einen separaten staging key statt eines anonymen shared credential.

Nutze die API base URL für /v1 resources. Nutze die OAuth issuer URL für /oauth/authorize, /oauth/token, /oauth/device_authorization, /oauth/revoke, /oauth/introspect und RFC-8414-Metadaten unter /.well-known/oauth-authorization-server. OIDC-Clients nutzen /.well-known/openid-configuration und /.well-known/jwks.json; ein 503 bedeutet ein OAuth-only Deployment, an das der openid scope nicht gesendet werden darf. Der kanonische Transport bleibt auf dem Apex https://moddingflow.com/v1; /api/v1 ist der kompatible Alias. Ein separater API-Host ist nicht erforderlich.

Stable v1 nutzt REST/JSON over HTTPS. Read endpoints bleiben GET resource routes, einschließlich GET /v1/uploads/{upload_id} für upload-session status, während write endpoints POST/PATCH mutations bleiben und lifecycle actions explizite action routes wie /v1/uploads/{upload_id}/complete, /v1/mods/{mod_id}/versions/{version_id}/publish und /v1/install-plans:resolve nutzen. Public clients adressieren Dateien über artifact_id, upload_id und download_session_id, nie über storage object keys, provider bucket names oder signed URL secrets.

GET /v1/uploads/{upload_id}/v1/JSON/PATCH/api/v1/oauth/token/oauth/revoke/oauth/authorize/oauth/introspect/.well-known/jwks.jsonhttps://moddingflow.com/v1/install-plans:resolvehttps://moddingflow.com/v1/oauth/device_authorizationhttp://127.0.0.1:3000/api/v1https://moddingflow.com/api/v1/v1/uploads/{upload_id}/complete/.well-known/openid-configuration/.well-known/oauth-authorization-server/v1/mods/{mod_id}/versions/{version_id}/publish

Native-, Desktop-, Mobile-, CLI-, lokale und Server-Apps mit PKCE S256, Device Flow, Registrierung ohne Secret oder kontoverwalteten vertraulichen Credentials integrieren. OAuth

Runnable examples

3

Öffne das OpenAPI JSON, konfiguriere apiBaseUrl https://moddingflow.com/v1 und oauthIssuerUrl https://moddingflow.com und wähle den Job: Mod Manager install/download, creator upload/publish, catalog/search oder Agent Gateway. API compatibility namespace: https://moddingflow.com/api/v1. Für creator automation prüft npm run api:cli -- auth check das Credential der Umgebung; npm run api:cli -- publish --mod-id <id> --archive <path> --version <version> führt validation, direct upload, scan polling und publish aus. Separate upload create, resume, complete und status commands verwenden eine explizite geschützte state file.

/searchapi:cli/publish/downloadhttps://moddingflow.comhttps://moddingflow.com/v1https://moddingflow.com/api/v1

Anonymer curl ohne API-Schlüssel, Bearer-Token oder spezielle Header: curl -X POST https://moddingflow.com/v1/install-plans:resolve -H "Content-Type: application/json" -d "{\"game_slug\":\"skyrim-se\",\"game_version\":\"1.6.1170\",\"mod_ids\":[\"11111111-1111-4111-8111-111111111111\"],\"include_optional\":false}". TypeScript: const client = new ModdingflowPublicApiClient(); await client.resolveInstallPlan({ body: { game_slug: "skyrim-se", game_version: "1.6.1170", mod_ids: [modId] } }); C#: var plan = await client.ResolveInstallPlanAsync(new ResolveInstallPlanRequest { GameSlug = "skyrim-se", GameVersion = "1.6.1170" }); Python: client = ModdingflowPublicApiClient(); plan = client.resolve_install_plan(body={"game_slug":"skyrim-se","game_version":"1.6.1170"}).

/jsonhttps://moddingflow.com/v1/install-plans:resolve

Creator automation startet mit POST https://moddingflow.com/v1/uploads, sendet bytes direkt an storage, erneuert multipart signed parts bei Bedarf, pollt GET https://moddingflow.com/v1/uploads/{upload_id}, completes upload, wartet auf ready oder failed, erstellt dann einen version draft und veröffentlicht. Verwende einen Idempotency-Key pro logischer create/update Operation, damit retries keine duplicate drafts erzeugen.

/updateIdempotency-Keyhttps://moddingflow.com/v1/uploadshttps://moddingflow.com/v1/uploads/{upload_id}

Reference, SDK und package policy

3

Nutze die API reference page für endpoint list, request/response schemas, scopes, servers, deprecation metadata und examples aus OpenAPI.

/response

Bis packages veröffentlicht sind, gilt das SDK als repo-only source artifact. Öffne den SDK source page mit source archive links und connection snippets, nutze danach repo/local imports: TypeScript imports sdk/typescript/src/moddingflow-public-api.ts, C# references sdk/csharp/Moddingflow.PublicApi, und Python adds sdk/python to PYTHONPATH before importing sdk/python/moddingflow_public_api. SDK source ist noch not published to npm, PyPI, or NuGet. Lokalisierte Textfelder wie title, summary und description bleiben language-code maps: TypeScript exposes [key: string]: string, Python exposes dict[str, str], and C# exposes Dictionary<string, string>. Python request DTOs behalten OpenAPI required fields mit Required[...] und NotRequired[...], sodass type checker install-plan bodies ohne game_slug oder game_version melden. Generierte Clients führen standardmäßig höchstens drei Versuche aus und wiederholen nur sichere/idempotente Methoden oder Schreibvorgänge mit Idempotency-Key. Sie berücksichtigen Retry-After und RateLimit-Reset mit begrenztem exponentiellem Backoff und Jitter, stellen die finalen Request-/Trace-IDs bereit und können abgelaufene signierte Download-URLs über einen expliziten Resolve-Hook erneuern. Regenerate and verify local artifacts with npm run api:sdks:generate und npm run api:sdks:check. Das Release Gate führt zusätzlich npm run api:sdks:compile aus; dabei werden npm-, Wheel- und NuGet-Artefakte lokal gepackt und in echten Consumern installiert sowie CLI und GitHub Action geprüft, ohne Registry-Pakete zu veröffentlichen.

Die Support/EOL-Matrix in docs/public-api/SDK-SUPPORT-AND-EOL.md führt jede SDK-, CLI- und Action-Version getrennt vom contract release 1.0.0-foundation sowie runtime floors und distribution state auf. Die aktuellen Artefakte sind Preview-Quellpakete ohne Registry-Verfügbarkeit, SLA, Signatur oder stabile EOL-Zusage. Ein stabiles Supportfenster beginnt erst nach einer clean immutable publication und einer Aktualisierung der Matrix mit datierten Zusagen.

/localsdk/python/Trace-IDs/EOL-Matrix/idempotenteapi:sdks:checkIdempotency-Keyapi:sdks:compileapi:sdks:generatesdk/csharp/Moddingflow.PublicApisdk/python/moddingflow_public_api/public-api/SDK-SUPPORT-AND-EOL.mdsdk/typescript/src/moddingflow-public-api.ts

Backwards compatibility policy: stable v1 old clients laufen während des ganzen support window weiter. Public operationIds, fields, scopes, error codes, headers, cursor semantics, idempotency und lifecycle behavior dürfen nicht entfernt, umbenannt oder in einen incompatible type geändert werden, außer über eine neue major version oder einen abgeschlossenen deprecation path. Compatible additive fields können im aktuellen v1 contract erscheinen, wenn old clients sie ignorieren können; new request fields müssen optional, nullable oder mit defaults versehen sein. New endpoints können in v1 ergänzt werden, wenn sie keinen bestehenden stable flow ersetzen und kein versteckter prerequisite werden. New enum/status values brauchen tolerant client guidance, docs und SDK updates. Beta oder experimental endpoints müssen marked with x-moddingflow-stage=beta, x-moddingflow-stage=experimental sein oder in einem future /v1/beta/* path liegen, und sie dürfen nicht required for stable flows sein. Deprecated operations und HTTP-visible capabilities nutzen den Deprecation response header als RFC 9745 Structured Field date, Sunset als RFC 8594 HTTP-date und Link rel="deprecation" für den migration guide. Breaking removals brauchen at least 90 days warning oder two stable API releases, einen migration guide mit replacement, detection, rollout, deadline und support contact sowie einen dedicated changelog entry. Any deprecated OpenAPI operation must include x-deprecation-date, x-sunset-date, x-migration-url, and x-changelog-url; das OpenAPI lint gate lehnt unvollständige deprecation metadata ab. Das Repository Release Gate lehnt Sunset außerdem ab, solange die genauen Daten nicht an committed migration, ready replacement, dated telemetry und approved support-owner evidence gebunden sind.

Release Notes, Migration-Guide-Vorlagen und stable-v1 Changelog Evidence stehen auf der API-Changelog.

/status/v1/beta/stage=betastage=experimental

Webhook automation

1

Nutze POST /v1/webhook-subscriptions mit webhooks:write für eine owner-scoped Subscription auf mod.updated, version.published, file.ready, file.failed, upload.completed, scan.completed, token.changed, app.changed oder account.access.changed. Targets müssen öffentliches HTTPS auf Port 443 verwenden. Die API gibt das Vault-backed whsec_ signing_secret einmal zurück; POST /v1/webhook-subscriptions/{subscription_id}/rotate-secret liefert eine neue Version mit begrenztem Overlap Window. Prüfe X-Moddingflow-Signature als HMAC-SHA256 über `${timestamp}.${raw_body}` mit X-Moddingflow-Timestamp und lehne stale Timestamps ab. Der versionierte Body enthält spec_version, stabile event_id, delivery_id, type, version, occurred_at, opaque Subject-IDs und data. Delivery ist at-least-once und ungeordnet: schnell bestätigen, asynchron verarbeiten, nach event_id deduplizieren und den neuesten State abrufen. account.access.changed enthält nur Event-ID, monotone Access Revision, Zeit und Kategorien; lies danach /me neu, statt einer geordneten Entitlement-Momentaufnahme zu vertrauen. Automatic Retries nutzen exponential backoff und enden in exhausted. Manual Redelivery über POST /v1/webhook-deliveries/{delivery_id}/redeliver mit Idempotency-Key erstellt eine neue delivery_id mit Link zum Original und behält event_id. GET /v1/webhook-deliveries mit webhooks:read zeigt delivery_status, attempt_count, next_attempt_at, last_response_status, begrenzte Latenz-, bereinigte Response-Snippet-, Retry- und Link-Daten. Wiederholte terminale Fehler können disable the subscription.

Bei Upload-Trust-Übergängen hält scan.completed das unveränderliche Scan-Ergebnis einschließlich Quarantäne fest. Eine spätere manuelle Freigabe erzeugt ein separates file.ready-Event; kein logisches Ereignis wird überschrieben, und Empfänger können beide unabhängig deduplizieren.

GET /v1/webhook-deliveriesPOST /v1/webhook-subscriptionsPOST /v1/webhook-deliveries/{delivery_id}/redeliverPOST /v1/webhook-subscriptions/{subscription_id}/rotate-secret/mewebhooks:readwebhooks:writeIdempotency-Key

Operations, limits und support

4

Eine erfolgreiche Version-Mutation-Response ist das authoritative committed Ergebnis dieser Operation und immer private, no-store. Anonyme Catalog-/Version-GETs revalidieren den shared cache, behalten einen weak representation ETag und verwenden public, max-age=0, s-maxage=0, no-cache, must-revalidate. Das Catalog-Freshness-SLO ist p95 höchstens 15 Sekunden, Search-Index-Freshness p95 höchstens 1800 Sekunden; das Dashboard nutzt das eigene Fenster jedes Ziels und berücksichtigt das Alter unfertiger Jobs, daher kann es nach Recovery ehrlich critical bleiben. Catalog-Visibility ist nie die Commit-Bestätigung; lösche keine Historical Evidence für ein grünes SLO. Mod/ModVersion PATCH erfordert genau einen strong quoted If-Match aus Create, authenticated Detail oder dem vorherigen PATCH: Fehlt er, folgt 428 precondition_required; malformed, weak, wildcard oder list values liefern 412 precondition_failed ohne Mutation; ein syntaktisch gültiger stale validator liefert 412 mit dem aktuellen ETag. Nach 412 Detail abrufen, Änderung rebasen und den neuen ETag mit einem neuen Idempotency-Key verwenden; kein blind retry.

Die cached PublicModVersion artifact expansion erfordert actual AV scan_status=clean, lifecycle=ready und publication state=published und bleibt eventual. Direct Download Resolve und Install-plan Resolve sind private point-in-time reads über ein eligible target, dessen established database state approved oder published sein kann. Direct eligibility ist nicht published-only und nicht legacy-only; fordere Resolve erneut an, wenn sich Version, Artifact, Dependency, Entitlement oder Publication State geändert haben könnten.

GET /v1/uploads/{upload_id} liefert den current database state zum Request-Zeitpunkt, während Worker-Transitions eventual sind. Poll Upload Status und job.statusEndpoint bis zu einem terminal state. Provider Progress ist nur bei progress.available=true authoritative; progress.available=false bedeutet unknown, nicht zero bytes und nicht den Verlust akzeptierter multipart parts.

Ein Install Plan ist ein deterministic private/no-store request-time snapshot mit ETag und keine live subscription. Resolve ihn nach einer späteren Änderung an Version, Artifact, Dependency, Entitlement oder Publication erneut.

Webhooks sind feature-gated. Wenn Management und Delivery aktiviert sind, ist Delivery eventual, at-least-once, replayable und unordered: Antworte schnell mit 2xx, deduplicate nach event_id, tolerierte replay und reordering und fetch den latest state. Webhook Arrival bestätigt keine Mutation; solange einer der Gates deaktiviert ist, wird keine Delivery versprochen.

GET /v1/uploads/{upload_id}age=0maxage=0/no-store/ModVersionstatus=clean/Version-GETsavailable=trueIdempotency-Keylifecycle=readystate=publishedavailable=false

Die Pipeline bleibt fail closed und behauptet keine cross-provider transaction. Create committet zuerst einen once-only Byte-Budget-Checkpoint für eine Request-Hash-Generation und reserviert danach Session/File Intent zusammen mit dem upload.accepted Audit atomar vor Provider Work. Eine verlorene Antwort zwischen beiden Checkpoints spielt dasselbe Budget-Ergebnis erneut ab; Exact Replay berechnet und auditiert daher nicht doppelt. Jeder single PUT wird mit If-None-Match: * signiert; seine maximale 900-second URL Lease wird nach dem Signing und vor der Response unter Row Lock checkpointet, und ein abort-winning Checkpoint verwirft die URL. Ein conditional 412 ist ein ambiguous existing write: Der Client ruft complete auf, wo Server HEAD, immutable Seal und SHA-256 authoritative sind. Nach Provider Completion kopiert ein gemeinsamer Session-Level Claim den exakten Client-Source-ETag bedingt in einen write-once server-only Seal. Der Seal Key wird vor CopyObject gespeichert, eine verlorene Copy-Antwort wird durch exakte HEAD-Prüfung wiedergefunden, und konkurrierende Completion Keys können den gebundenen Seal nicht überschreiben. Die immutable Identity erreicht den queued scan checkpoint mit pending SHA; der fenced Worker streamt und attestiert den vollständigen Hash atomar vor Validation, AV oder Final Copy. Nach einer verlorenen Antwort wiederhole denselben normalisierten Request mit demselben Idempotency-Key; nach Checkpoint und Job genügt Status-Polling.

Eine content-addressed final copy ist noch nicht ready. Same-SHA Promotion wird durch einen dauerhaften SHA/Bucket/Key Claim serialisiert: Der Gewinner besitzt das canonical MIME und nutzt den Cloudflare Header cf-copy-destination-if-none-match: *, während ein fresh duplicate wartet oder den exakten ready Blob übernimmt, ohne einen normalen scan attempt zu verbrauchen. Das Contention-Polling wächst exponentiell von einer auf 30 Sekunden und ist pro Claim auf 15 Minuten begrenzt. Die ersten zwei dauerhaften token-fenced Yields stellen den normalen Attempt atomar wieder her und stellen den Job mit einem von der Datenbank bestimmten Jitter von 30 bis 60 Sekunden erneut in die Queue; der dritte erstellt atomar Manual Review und Quarantäne, statt unbegrenzt weiter zu versuchen. Lost-Response-Replay liefert dasselbe persistierte queued oder quarantined Ergebnis. Eine verlorene Copy-Antwort wird nur akzeptiert, wenn HEAD SHA-Metadata, Größe, canonical MIME und einen nonblank Provider-ETag validiert. Ein accessible attested blob muss existieren, bevor ein atomic ready binding den immutable Blob, das Logical File und die Upload Session zusammen mit Audit und file.ready Event verknüpft. Während der manuellen Prüfung bleibt die Quarantäne bis zur Provider-Attestierung bestehen: Eine Freigabe committet Ready-Binding, Review-Entscheidung, Decision Audit und Event atomar; eine Ablehnung committet rejected Session, Datei, Review, Decision Audit und Event atomar. Transactional publish und durable outbox commit erfolgen in einer Database Transaction; Metadata kann vor dem Ready Binding nicht veröffentlicht werden.

Heartbeat-backed Claim Tokens grenzen jede Scan-Mutation ab: Ein stale Worker kann nach Reclaim weder Retry noch Clean-, Quarantine-, Rejection-, Audit- oder Event-State ändern. Jeder neue Ready-, Quarantine- oder Rejection-Übergang committet Session, Datei, Job, Audit und das deterministische kanonische Event in einer Database Transaction. Exact Replay validiert das vorhandene terminale Envelope; nach einer uneindeutigen RPC-Antwort akzeptiert der Worker nur das exakt neu geladene Envelope. Bounded Reconciliation repariert nur explizite Legacy Gaps und überspringt aktive Claims. Deployed webhook delivery wird nicht versprochen. Account-Inbox-Benachrichtigungen sind keine Lifecycle Acknowledgements; maßgeblich bleibt der machine-readable Upload-Status.

Vor Provider-Konfiguration oder normalen Scan Claims stellt ein begrenzter reiner Datenbank-Sweep stale Processing Claims mit ausgeschöpften Versuchen wieder her, ohne Storage- oder Scan-Arbeit zu wiederholen. Kohärenter State wechselt atomar in canonical Manual Review und Quarantine; inkohärenter State setzt nur den exakten token-fenced Job mit manual_intervention_required terminal auf Failed, damit das Problem sichtbar bleibt, ohne Session- oder File-State zu erfinden. Eine fehlerhafte Zeile blockiert keine unabhängigen Jobs, und Recovery verbraucht dasselbe begrenzte Worker-Batch-Budget.

Recovery wiederholt zuerst den bewiesenen Seal, die content-addressed copy oder das Binding. Cleanup hat einen eigenen Claim Token. Für Single Staging schreibt durable Stage 1 bedingt einen zero-byte tombstone und validiert beim Provider ETag, LastModified, Metadata Token und size=0; der Tombstone bleibt bis zur persisted latest URL Lease und mindestens 16 Minuten bestehen. Durable Stage 2 führt Exact Delete, HEAD-Abwesenheitsprüfung und DB Completion aus; Crash Replay setzt den aktuellen Stage fort. Multipart Cleanup bricht jeden Exact-Key Upload ab und relistet ihn, und jeder Seal-Claim-Key wird gelöscht und per HEAD geprüft; abgelaufene uploaded Sessions ohne Checkpoint sind eingeschlossen, Quarantäne behält ihren Seal. Generation Byte-Budget Reservations werden erst nach Replay Window plus Sicherheitsmarge gelöscht. Die gewünschte CORS Policy enthält If-None-Match, und der Object-Level Probe bestätigt Conditional Copy plus Late-PUT Tombstone Rejection, aber live CORS/lifecycle/lock evidence bleibt BLOCKED bis die Operator Inputs CLOUDFLARE_API_TOKEN, MODDINGFLOW_R2_FINAL_LOCK_MIN_SECONDS und MODDINGFLOW_R2_ALLOWED_BROWSER_ORIGINS vorliegen; ein live Deployment wird nicht behauptet. Eine unbound final copy remains non-ready and non-publishable, ist never publishable und bleibt unter Retention/Lock bis zur PR-F3.13 reference-aware deletion. Numeric freshness bleibt PR-F2.6.3, deployed webhook enablement bleibt PR-F8.14.

/File/Locksize=0/Bucket/KeyIdempotency-Key/lifecycle/lock

Die API wendet route, scope, body-size, byte-budget, download concurrency und abuse limits vor teuren side effects an. Download Leases erlauben 2 anonyme oder 4 authentifizierte Requests pro Actor und 16 pro OAuth/PAT Client, mit 300 Sekunden Ablauf; Byte Buckets sind 24 GiB anonym, 40 GiB authentifiziert und 24 GiB Upload. Multipart nutzt standardmäßig 16 MiB × 4, höchstens vier signed parts pro Request und 64 MiB Payload in Flight. Oversized bodies liefern 413. Overloaded oder abusive clients erhalten 429 mit Retry-After und RateLimit headers sowie retryable, retry_after_seconds und einem nicht sensiblen quota_bucket. Jeder application/problem+json error enthält außerdem code, docs_slug, request_id, trace_id und X-Request-Id; scope- und validation errors ergänzen required_scopes oder fields nur wenn umsetzbar. Error codes entwickeln sich innerhalb von v1 additiv, daher müssen clients unbekannte codes bewahren und auf den numerischen HTTP status zurückfallen.

/PAT/problem

Bevor du ein neues API artifact nutzt, prüfe, dass OpenAPI, SDK generation, compatibility checks, localized docs und reference rendering für den release bestanden wurden. Stable v1 verlangt zusätzlich contract_test_matrix coverage: DTO/schema, Problem Details, cursor pagination, upload-session lifecycle, download-grant lifecycle, OAuth/PAT scopes, webhook signature, webhook retry/redelivery, backwards compatibility und client flow smoke. Zusätzlich braucht es final_readiness_checklist coverage: public endpoints documented, opaque ID entity addressing, signed URL/resumable upload, download-grant downloads, multiple hash algorithms, async status/job endpoints, OAuth/PAT self-service, Problem Details, cursor-based pagination, webhook signatures and redelivery, Deprecation/Sunset policy, current OpenAPI spec, current FAQ and public documentation, passed tests and validations, known limitations list und first stable release notes. Fehlt ein endpoint in OpenAPI, gilt er als website-internal und nicht als public developer surface.

/PAT/job/schema/Sunset/resumable/redelivery
Moddingflow

Community, Mods und Diskussionen für Lieblingsspiele.

Projekt

NewsRanglisteAPIOAuthRegeln

Produkte

Moddingflow Premium

Website-Dokumente

NutzungsbedingungenDatenschutzCookie-RichtlinieImpressumWiderrufsinformationen

Support

FAQ

© 2026 Moddingflow. Alle Rechte vorbehalten.

Moddingflow
BETA

Spiele

Alle Spiele (13)Zuletzt hinzugefügt

Meine Spiele

Oblivion RemasteredMinecraftStarfieldFallout 3The Witcher 3Oblivion
ForumNewsRangliste