Scenes, assets and 3D models
This page describes the three parts that make up your game’s world: real-time scene (stage/room) registration, images uploaded from the panel and the server, and 3D models uploaded by an operator. Read it if you want to open city rooms from the server, manage icon and banner images, or serve models to the game.
What it does
- Scene: The room where the real-time plugin gathers players. The game server registers the scenes it needs at startup; registration is idempotent.
- Image (asset): PNG, JPEG or WebP. It is content-addressed: the address is the file’s
sha256digest, and the same file is stored once. Store banners, currency icons and content groupimagefields use this store. - 3D model: A
glb(or a converted source file) uploaded by an operator in the panel. Once published it is bound to an item or a character and the game gets it from the catalog.
The scene and image write endpoints depend on the scenes module; if the module is disabled, 404 with {"code":"module_disabled","module":"scenes"} is returned. The image and model read endpoints are core and work even when the module is disabled. Enable the module on the Game settings › Modules page.
Where it lives in the panel
| What you want to do | Panel page |
|---|---|
| Upload, preview, publish and archive a 3D model, add a clip | 3D models, Model profile |
| Bind a model to an item or a character | Content (built-in item/character groups) |
| Upload store banners and product images, currency icons | Store, Currencies |
| Moderate city chat (scene plugin) | City chat |
| See that the scene plugin is installed, and its permissions | Plugins |
Note
Panel help pages are not translated yet; the panel links above point to the Turkish source.
Data model (in plain words)
Scene
- The ID is derived from three parts:
plugin_id(the plugin),module_id(the real-time module) andkey(at most 96 characters). The same triple always resolves to the same scene. capacity: The room’s player capacity; at most 10,000.state:open,draining(emptying) orclosed.partition_id: The ID of the partition the scene runs on in the distributed setup (generated by the server).
Image
- The type is derived from the first bytes of the file; the
Content-Typeheader is only advisory. Accepted types areimage/png,image/jpeg,image/webp. - At most 2 MiB; width and height are each at most 4096 pixels.
- The response gives
sha256,contentType,byteSizeandcreated(whether it was written in this call).
3D model
- An upload can be
glb, or it is converted from source formats such asfbx,obj,usdz,stl,blend,3mf,dxf. The conversion status isqueued,converting,ready,failed; the reason for a failure appears in the panel as a sentence in Turkish (for example an external resource reference, a budget overrun, a 2D DXF). - Every model is versioned; the published version appears in the catalog. The lifecycle is
active,archived,purged. - Default limits: uploaded file 50 MiB, environment quota 1 GiB, 200 models per environment, 20 versions per model, 10 uploads per operator per 10 minutes.
- The converter runs only on the amd64 architecture; on other architectures only
glbcan be uploaded.
Calls your game makes
| Method and path | Credential | What it does |
|---|---|---|
PUT /v1/scenes | server key | Provisions a scene idempotently |
PUT /v1/assets | server key | Uploads an image as a raw body |
GET /v1/assets | server key | Lists the environment’s images (cursor, limit) |
DELETE /v1/assets/{sha256} | server key | Deletes an image row (204) |
GET /v1/assets/{sha256} | no credential | Reads the image bytes |
GET /v1/model-files/{sha256} | no credential | Reads a published model’s glb file |
Management endpoints require Authorization: Bearer crx_live_<prefix>_<secret>; a client key gets 403.
Provisioning a scene
PUT /v1/scenes
Authorization: Bearer crx_live_<prefix>_<secret>
Content-Type: application/json
{ "plugin_id": "package-ride", "module_id": "package-ride.presence", "key": "istanbul-1", "capacity": 200 }
{ "scene_id": "…", "plugin_id": "package-ride", "module_id": "package-ride.presence", "key": "istanbul-1", "partition_id": "…", "capacity": 200, "state": "open", "created": true }
- If the scene does not exist, it is written (
201,created: true); if it exists, it is returned unchanged (200,created: false).Idempotency-Keyis not needed. 400: the ID, key or capacity is invalid (body errors are400too).403: a client key.409: a scene with a different ID on the same key.422: the plugin is not enabled in this environment.
For a plugin’s real-time modules and the player-side flow, see Realtime: overview and Plugins.
Uploading an image
PUT /v1/assets
Authorization: Bearer crx_live_<prefix>_<secret>
Content-Type: image/png
<raw PNG bytes>
{ "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", "contentType": "image/png", "byteSize": 18234, "created": true }
201 with created: true is the first write; if the same bytes already exist, 200 and created: false are returned and the row does not change, so the upload is idempotent. An empty body, an unrecognized type, a size over 2 MiB or a width/height over 4096 pixels is rejected with 400 (error codes asset_empty, asset_unsupported_type, asset_too_large, asset_dimensions_too_large).
To show the image in the game, use <img src="…/v1/assets/<sha256>?env=<environment uuid>">: the endpoint is unauthenticated, and it takes the environment from the x-crx-env header or (for <img>/texture loaders that cannot send headers) from the env query parameter. The response carries the sha256 as its ETag and can be cached indefinitely (immutable); if If-None-Match matches, 304 is returned. A new image means a new sha256, that is a new address.
Note
The image and model read endpoints send cross-origin readable response headers so that a browser’s texture loader can use them. The other public endpoints grant CORS only to origins in the environment’s domain list; see Architecture and hosting.
Warning
DELETE /v1/assets/{sha256}deletes only the row; the store does not know whether other records (a product, an icon, content) refer to this image. Make sure the image is unused before deleting it.
Bringing a 3D model into the game
Upload and publish the model in the panel and bind it to an item or a character. The game reads the model’s address and computed facts (triangle count, bones, clips, bounding box) from the catalog; model.glb.url has the form /v1/model-files/<sha256>?env=<environment uuid>. Details: Content groups › Catalog and Game catalog integration (docs/oyun-katalog-entegrasyonu.md) (Turkish).
GET /v1/model-files/{sha256} is unauthenticated and content-addressed:
- The environment is given with the
x-crx-envheader or theenvquery; if both are given and differ, or neither is present,400. - Only the
glbfile of a model that is ready, whose files are retained and which is not deleted is returned;404for a deleted model. - A matching
If-None-Matchgives304without opening the file. A200response carriesContent-Length, themodel/gltf-binarytype and indefinite cache headers.Rangeis not supported. - The same
sha256is always the same bytes: cache the file bysha256and do not download it again.
Note
Model upload and publishing are done only from the panel; there is no public write endpoint for models. The Unity SDK has no catalog and model read helpers; use raw REST.
Versioning and replay safety
PUT /v1/scenesandPUT /v1/assetsare naturally idempotent (a derived ID, a content address); they do not ask forIdempotency-Key.- A model file and an image are content-addressed: the same address never gives different bytes.
- Model versions are tracked in the panel; the game always sees the current published version from the catalog.
Events
These surfaces produce no webhook events. A model change is reflected in the catalog as a new sha256; poll with ETag.
Limits
- An image is at most 2 MiB and 4096×4096 pixels; only PNG, JPEG, WebP.
- Scene
keyis at most 96 characters,capacityat most 10,000. - The model default limits are above (50 MiB, 1 GiB quota, 200 models, 20 versions).
- The
GET /v1/assetspage size is at most 200 (default 50).
Common errors
| Symptom | Cause | Fix |
|---|---|---|
422 (scene) | The plugin is not enabled in this environment | Enable the plugin (Plugins) |
409 (scene) | A scene with a different ID on the same key | Change the key |
400 (image) | The type was not recognized, or 2 MiB or 4096 pixels was exceeded | Upload PNG/JPEG/WebP under 2 MiB and 4096 pixels |
<img> does not load | env or x-crx-env is missing | Add ?env=<environment uuid> to the address |
404 (model file) | The model was deleted or is not ready yet | Check the model field in the catalog |
The model is failed in the panel | A conversion error | Fix the file according to the reason the panel shows |
Working example
Uploading and reading an image:
curl -X PUT "$API/v1/assets" \
-H "Authorization: Bearer $SERVER_KEY" -H "Content-Type: image/png" \
--data-binary @banner.png
curl "$API/v1/assets/<sha256>?env=$ENV" -o banner.png