Editing content
Apply typed content operations to documents.
Creating a document makes its metadata; content operations fill in what's inside. These are typed per document type — you describe what to change ("add this event", "make this the active animation"), never raw document internals — and the write reconciles with anyone editing live, so a person watching the document sees your change appear.
POST /api/v1/worlds/{worldId}/documents/{documentId}/contentTimelines
timeline.addEvent adds one or more events to a timeline document.
curl -X POST \
https://vvd.world/api/v1/worlds/WORLD_ID/documents/DOC_ID/content \
-H "Authorization: Bearer $VVD_KEY" \
-H "Content-Type: application/json" \
-d '{
"ops": [
{ "op": "timeline.addEvent", "label": "The First Battle", "dateMs": 0 },
{ "op": "timeline.addEvent", "label": "The Sundering", "dateMs": 31536000000,
"description": "The sky broke.", "precision": "year" }
]
}'Response:
{
"documentType": "timeline",
"applied": 2,
"created": [
{ "id": "evt-…", "label": "The First Battle" },
{ "id": "evt-…", "label": "The Sundering" }
]
}Animations
animator.setActiveClip changes which animation clip is active on an animator document.
The active clip is shared document state, so a client polling the document (a game engine,
say) sees the change on its next read — the basis for driving an external runtime from vvd.
curl -X POST \
https://vvd.world/api/v1/worlds/WORLD_ID/documents/DOC_ID/content \
-H "Authorization: Bearer $VVD_KEY" \
-H "Content-Type: application/json" \
-d '{ "ops": [ { "op": "animator.setActiveClip", "clipId": "Swim" } ] }'Applying an operation to a document type that doesn't support it returns a clear error listing what is supported. More types gain content operations over time.
Reading content
GET /api/v1/worlds/{worldId}/documents/{documentId} returns the document's live
content alongside its metadata — read from the current document state, so it reflects the
latest edit rather than a stale projection:
{
"id": "…",
"name": "Nemo",
"documentType": "animator",
"content": {
"data": {
"model": { "url": "https://…/nemo.glb", "name": "nemo.glb" },
"clips": [ { "id": "Idle" }, { "id": "Swim" }, { "id": "Walk" } ],
"activeClipId": "Swim"
},
"source": "live",
"text": "Nemo Idle Swim Walk"
}
}content.source is live (read from the current document state), stored (a fallback
projection), or empty. content.data is the tool's own typed shape — for an animator, its
model, clip list, and active clip; for a card, its name, aliases, properties, and sections.