Skip to content
Guides— browse docs
On this page

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}/content

Timelines

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" } ] }'
Note:

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.