A small, strict JSON schema that describes any 3D asset inscribed on Bitcoin so it renders correctly across Bitverse, JUNGL, KENOBI hubs, and any other open metaverse that adopts it. This is a strict superset of avatar-interop.
Two ways to attach a metadata document to your asset inscription:
application/json, body = the AssetMetadata JSON. The
id of this sibling becomes the
metadata_inscription_id stored in the registry.asset.glb +
metadata.json with content-type
application/bitverse-bundle+json.{
"v": 1,
"kind": "prop",
"name": "Pixel Mushroom Guardian",
"description": "A friendly mushroom NPC for cozy gardens.",
"license": "CC0-1.0",
"authorAddress": "bc1pae6v9gz...75ye5e",
"authorHandle": "polygonal-mind",
"url": "https://arweave.net/abc.../mushroom.glb",
"thumbnailUrl": "https://arweave.net/abc.../mushroom.png",
"scale": 1.0,
"tags": ["pixel", "fantasy", "garden", "friendly"],
"compat": { "minSdk": "1.0.0", "worksOn": ["bitverse", "jungl"] }
}
| Field | Type | Notes |
|---|---|---|
v | number | Spec version. Today: 1. |
kind | string enum | One of avatarpropimageaudiovideohtmlkenobiscene-kit |
name | string | Display name. Up to 80 chars. |
license | string | SPDX license id. CC0-1.0 strongly recommended. |
authorAddress | string | Author wallet (BTC). Drives attribution + royalties. |
url or inscriptionId | string | Where the actual asset bytes live. At least one required. |
{
"v": 1, "kind": "avatar",
"name": "Onchain Monkey #4288",
"license": "CC0-1.0",
"authorAddress": "bc1pae6...",
"inscriptionId": "abc...i0",
"avatar": {
"vrmVersion": "1",
"pose": "T",
"baseScale": 1.0,
"eyeHeightM": 1.6,
"maxWalkSpeed": 5.5,
"animations": {
"idle": "ord://idle.glb",
"walk": "ord://walk.glb"
}
}
}
The avatar block is a strict superset of avatar-interop so any VRM that already declares it is automatically compatible with Bitverse.
{
"v": 1, "kind": "audio",
"name": "Lo-fi Bitmap Beat",
"license": "CC-BY-4.0",
"authorAddress": "bc1pae6...",
"inscriptionId": "abc...i0",
"media": {
"loop": true,
"volume": 0.8,
"falloffFullM": 2,
"falloffSilentM": 10,
"interactive": true
}
}
Falloff metres override the renderer defaults (full at 2m, silent
at 10m for audio; full at 3m, silent at 12m for video).
interactive = false will mute click-to-toggle for ambient
sources you don't want guests muting.
{
"v": 1, "kind": "html",
"name": "Mini Tetris Cabinet",
"license": "MIT",
"authorAddress": "bc1pae6...",
"inscriptionId": "abc...i0",
"html": {
"capabilities": ["scene", "events", "broadcast"],
"preferredSizeM": { "w": 2.4, "h": 1.6 },
"facing": "billboard"
}
}
HTML scenes load inside an iframe sandboxed with
sandbox="allow-scripts" only โ no same-origin, no popups,
no pointer lock. Capabilities listed here MUST be a subset of the
sandbox host's allowed list. The visitor sees a one-time consent
dialog before mounting any HTML scene that requests AI / persist /
multiplayer permissions.
{
"v": 1, "kind": "scene-kit",
"name": "Cozy Cottage Starter",
"license": "CC0-1.0",
"authorAddress": "bc1pae6...",
"url": "https://arweave.net/...kit.json",
"sceneKit": {
"items": [
{ "ref": "polygonal-mind/cottage", "refKind": "cc0", "pos": { "x": 0, "y": 0, "z": 0 } },
{ "ref": "abc...i0", "refKind": "inscription", "pos": { "x": 2, "y": 0, "z": 1 } },
{ "ref": "polygonal-mind/lantern", "refKind": "cc0", "pos": { "x": 1, "y": 0, "z": 1 }, "scale": 0.5 }
]
}
}
Scene kits are bundles a creator can publish once and visitors can drop with a single click. Children are placed relative to where the visitor confirmed the kit anchor.
The validator preserves any field it doesn't know about. If the spec adds a new section in v2, v1 hosts still display the asset using the v1 fields, and forwarding the metadata between platforms doesn't drop data.
Plugin authors and tooling can import the typed schema directly:
import {
parseAssetMetadata,
defaultPropMetadata,
type AssetMetadata,
} from "@bitverse/sdk/interop";
const meta = parseAssetMetadata(json);
if (!meta) throw new Error("metadata failed validation");
console.log(meta.kind, meta.name);