Live wearable and Unreal contract
The deployed Universal Item upload, finalize, status, download, and Unreal rendition contract, audited against helix3.
Live wearable and Unreal contract
This page records the currently deployed Universal Item transport behavior. It was audited on July 29, 2026 against the helix3 API and validator worker. The broader Interactive Universal Items handoff remains the executable target for shared behavior, authoritative state, runtime adapters, and default-on scrubbed Vault publication. Those target features are not implied by the live upload API described here.
Run the Unreal test
A sendable, end-to-end dual-format upload and download sequence.
Read the target runtime handoff
The shared manifest, authority, state, character ability, and Vault publication contract.
Item-first upload
Create one product, upload each source rendition, finalize each source asset, then wait for every rendition the runtime may consume to become ready:
POST /api/v1/universal-itemsonce.- PUT the web GLB and every Unreal file to the returned presigned URLs.
- Finalize the web asset once and the Unreal asset once.
- Poll the item until the required assets report
status: "ready". - Download only from the public URLs in the read response.
One dual-format wearable has one Universal Item ID and two creator-uploaded source asset rows:
| Source row | Shape |
|---|---|
rendition: "web" | One GLB declared with filename, mimeType, and sizeBytes. |
rendition: "unreal" | Cooked packaged output—normally the matching .pak, .utoc, and .ucas files—declared through files[], plus engineVersion and targetPlatforms. |
Do not create separate items for web and Unreal. A generated thumbnail asset row may appear
asynchronously after processing. It is a derived rendition, not a third source upload, so consumers
must not assume the final assets array has exactly two rows.
Wearables also require the live Character Creator fields:
kind: "wearable"usage: "wear"- one valid
slot, such asCosmetic.Slot.Clothing.Top genders: ["male"],["female"], or["male", "female"]
The generic asset DTO can represent mixed fields, but the canonical integration shape keeps web and Unreal on separate rows. Unreal-only engine and platform claims cannot truthfully live on the web row.
Finalize and readiness
Create returns presigned PUT URLs without waiting for bytes. Finalize operates on one asset, not
one file. It checks every Unreal file that declared a SHA-256, runs the applicable moderation gate,
records metadata.pipeline.finalizedAt, and moves the asset from awaiting_upload to pending.
Finalize means verified and queued; it does not mean usable.
awaiting_upload → pending → processing → ready
↘ rejected | failedStatus is the trust boundary
The CDN URLs are allocated before upload. During the deployed probe, all three uploaded objects were
downloadable while both source assets still reported awaiting_upload. Never load or mount a
rendition merely because its URL exists or returns HTTP 200. Require asset.status === "ready".
Fresh deployed requests returned HTTP 201 from both asset finalize calls. The deployed OpenAPI document currently describes the same success response as HTTP 200. This is an unresolved contract discrepancy, tracked in backend task CH-1162. Until that task settles the stable status code, record 201 as observed runtime behavior and 200 as the published OpenAPI metadata; neither response code makes an asset ready.
Read and select renditions
The public item read returns the item and all of its current asset facts. Runtimes own selection:
- Web may use only a ready
webrendition. - Unreal should prefer a ready
unrealrendition whose engine version matches the running client and whosetargetPlatformsincludesWin64. - Unreal may fall back to a ready web GLB when the client supports that path.
- A
thumbnailrow is presentation metadata, never a runtime replacement for either source.
cdnUrl and files[].url are public CDN URLs. uploadUrl is temporary and appears only in
create/update responses.
Public URLs are mutable pointers
The public URLs are durable and deterministic, but they are not immutable Vault versions.
PATCH /:itemId/assets/:assetId can re-declare files and overwrite the same object key. Invalidate
caches when status or build metadata changes. Pinned immutable URLs belong to the target Vault
version contract.
Live Unreal metadata and integrity
| Field | Deployed behavior |
|---|---|
engineVersion | The Unreal version used to cook the package and the runtime compatibility version consumers must match. It is stored per Unreal asset; x-engine-version wins over the body and omission defaults to 5.7. HELIX currently targets Unreal 5.7, but 5.7 is a HELIX target/default—not a requirement of the .pak/.utoc/.ucas format or transport API. |
targetPlatforms | Current Unreal runtime support is Win64 only. New Unreal assets must declare ["Win64"]; all other target values are unsupported. |
files[].sha256 | Optional, normalized to lowercase. When supplied, finalize reads the object, rejects missing or mismatched bytes with HTTP 422 sha256_mismatch, and corrects stored size to the measured length. |
| Asset revision | Not available. There is no immutable revision, build ID, release note, or asset history on a Universal Item asset. |
Publish Win64 packages only
HELIX does not currently support native Unreal packages for any target other than Win64. Cook,
publish, select, and mount the .pak/.utoc/.ucas set for Win64, and keep
targetPlatforms: ["Win64"] on the asset.
Do not relabel an older cook
Unreal 5.5 packages are not compatible with the current HELIX 5.7 runtime. Keep an existing 5.5
package row labeled engineVersion: "5.5"; changing only its metadata does not change the cooked
bytes. Re-cook the package with Unreal 5.7, publish the new .pak/.utoc/.ucas set with
engineVersion: "5.7", and wait for that asset to become ready before selecting it. Explicit patch
values such as 5.7.1 are accepted when they reflect the exact engine used for the cook.
Upload cooked packaged output, not loose Content Browser .uasset files. For an Io Store build,
keep the matching .pak, .utoc, and .ucas files together and send a SHA-256 for every file.
The live platform validates the envelope—file-key syntax, the 512-file cap, engine/platform syntax,
and optional checksums—but it does not parse or mount the package, prove the declared
engineVersion can load it, validate cook compatibility or dependencies, require a manifest,
enforce a complete expected file set, or validate Unreal naming conventions. Unreal binaries are
treated as non-visual and skipped by media moderation.
The current multipart endpoint, POST /api/v1/universal-items/upload, is web-only. Publish both
formats through the presigned JSON create flow, or add the Unreal source row afterward with
POST /:itemId/assets.
Live catalogue mode versus target Vault publication
The live libraryContribution field contributes a public, free Universal Item to the catalogue. It
is not the target scrubbed Vault-definition publication. The backend has
universal_items.vault_asset_id and immutable Vault versions, but Universal Item asset finalize
does not yet create or link that definition automatically.
The target remains:
- one immutable definition shared by Web and Unreal presentation adapters;
- separate owned, placement, session, and private state partitions;
- one authoritative function/event choke point with validation, permissions, idempotency, capabilities, and replication filtering;
- a first-party
ItemInteractionAbilityfor abstract input, sockets, animation, hands, camera, and movement channels; - default-on publication of a scrubbed definition to Vault, respecting the creator preference and an explicit per-publish opt-out.
The publish transform keeps manifests, clean defaults, functions/events, sockets, logic, compatibility, and pinned assets. It removes owner/inventory identifiers, live owned values, placement/world identifiers and transforms, bindings, occupants, scores, ammunition, cooldowns, timers, private values, runtime handles, and session state. Installing creates fresh IDs and revision-zero state. None of this target runtime/package surface is shipped by the rendition API today.
Verification and sources
The deployed transport round trip is preserved as a
dual-format test item.
It returned ready web and Unreal source assets, matching downloaded SHA-256 values, and a generated
thumbnail row after processing. That fixture proves the deployed byte-integrity flow only; it does
not prove a cooked package mounts. The sendable test below requires real .pak, .utoc, and
.ucas cooking outputs for that compatibility check.
Interactive Universal Items
Production implementation contract for portable items with authoritative behavior, typed state, character abilities, and default-on Vault publication.
Unreal dual-format wearable test
A sendable end-to-end test for publishing one wearable with Web and cooked Unreal package renditions.