WorldDeveloper HandbookOpen world.page ↗
World platform

Platform API reference

Generated from the existing service OpenAPI source. These routes remain available while the new Page service is implemented.

Existing service · legacy model

Authentication and authority

Existing browser APIs use the host-only secure World session cookie. Mutations require the expected Origin and session CSRF token. Membership, project authority and write permissions are checked by the service.

dev.world.page is documentation only. It has no account database, does not receive the world.page host-only cookie and does not proxy authenticated requests. There is no “try a production mutation” control here.

New Page provider boundary

IndexedDB and authenticated service adapters now implement the same boundary. The authenticated review is local-only; the public playground remains browser-local. New Page endpoints are not enabled on the live application.

provider.read(pageId, { signal })
provider.observe(pageId, onInvalidation)
provider.send(pageId, { body, widgets, requestId })

Existing HTTP operations

Filter by method, path or operation name using the search field. The schema is a compatibility reference; it does not describe the new Page service.

GET /api/v1/communities/{studioId}/studio-projects/{projectId}/native-imports

Published immutable native project snapshots only, newest insertion first, 48 per page. Project membership required; unfinished transfers are never listed.

Parameters: studioId (path), projectId (path), before (query).

POST /api/v1/communities/{studioId}/studio-projects/{projectId}/native-imports

Explicit native Animation/Storyboard transfer. Requires a normal web session, exact Origin, CSRF and project artist/manager authority. The UUID Idempotency-Key is bound to this account, destination and exact manifest bytes. A schema-version-2 protobuf manifest describes original files and every dependency; no local synchronization or existing-document replacement occurs. Current caps: 2 MiB manifest, 4096 assets, 8 GiB/asset, 16 GiB/transfer and per-project admitted bytes, 4 pending uploads/account, 200 retained snapshots/project. Pending transfers expire in seven days.

Parameters: studioId (path), projectId (path), X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/x-protobuf": {
      "schema": {
        "type": "string",
        "format": "binary"
      }
    }
  }
}
GET /api/v1/communities/{studioId}/studio-projects/{projectId}/native-imports/{importId}

Transfer status and up to 64 started assets. Pending transfers are private to their creator. Use after digest cursor for remaining progress; omitted manifest assets have not started.

Parameters: studioId (path), projectId (path), importId (path), after (query).

DELETE /api/v1/communities/{studioId}/studio-projects/{projectId}/native-imports/{importId}

Cancel only the creator’s unpublished transfer. Published originals are immutable and cannot be cancelled. Private staged objects/checksum state are removed by bounded maintenance, with repeat sweeps for late writes; idempotency tombstones remain.

Parameters: studioId (path), projectId (path), importId (path), X-CSRF-Token (header).

GET /api/v1/communities/{studioId}/studio-projects/{projectId}/native-imports/{importId}/files

Completed snapshots only. Lists up to 48 dependency references with original relative paths and byte lengths. Optional after cursor; no source bytes. Current project membership required.

Parameters: studioId (path), projectId (path), importId (path), after (query).

GET /api/v1/communities/{studioId}/studio-projects/{projectId}/native-imports/{importId}/assets/{digest}/source

Completed verified original, streamed one storage chunk at a time with access rechecks. One byte range supported; each response is at most 32 MiB to bound Worker subrequests. Larger clients use bounded ranges or the native chunk API. Optional name must be an original filename for this asset in the verified manifest. No public URL or browser blob buffering.

Parameters: studioId (path), projectId (path), importId (path), digest (path), Range (header), name (query).

GET /api/v1/communities/{studioId}/studio-projects/{projectId}/native-imports/{importId}/manifest

Original verified protobuf metadata. Completed files require current project membership; pending files require creator access. Download bytes never grant authority or imply codec support.

Parameters: studioId (path), projectId (path), importId (path).

PUT /api/v1/communities/{studioId}/studio-projects/{projectId}/native-imports/{importId}/assets/{digest}/chunks/{index}

Upload the next ordered 4 MiB chunk (short final chunk allowed). Length and SHA-256 must match the admitted manifest. Identical retries are safe; gaps and changed bytes fail. R2 is written before the conditional progress commit, which rechecks current permissions.

Parameters: studioId (path), projectId (path), importId (path), digest (path), index (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/octet-stream": {
      "schema": {
        "type": "string",
        "format": "binary"
      }
    }
  }
}
GET /api/v1/communities/{studioId}/studio-projects/{projectId}/native-imports/{importId}/assets/{digest}/chunks/{index}

Bounded original bytes. Revalidates current project access; pending data is creator-only. Reconstruct and validate originals/dependencies with their native codec before editing.

Parameters: studioId (path), projectId (path), importId (path), digest (path), index (path).

POST /api/v1/communities/{studioId}/studio-projects/{projectId}/native-imports/{importId}/assets/{digest}/verify

Advance server-owned whole-file SHA-256 by at most 256 KiB from stored bytes. Persisted private state and compare-and-swap make restart and concurrent retry safe. Clients repeat until verified; progress never exposes internal hash state. This bounds each verification call rather than hashing an entire movie in one request.

Parameters: studioId (path), projectId (path), importId (path), digest (path), X-CSRF-Token (header).

POST /api/v1/communities/{studioId}/studio-projects/{projectId}/native-imports/{importId}/commit

Publish one immutable snapshot only after every source/dependency passes its complete SHA-256. One conditional database write rechecks current account, membership and sponsorship. Replay returns the same import; no document is exposed before this point. Published snapshots appear in the Studio catalogue, directory references and immutable medium resolver. Original-file exports preserve source bytes; native whole-project install/Open and the WebGPU editor remain separate work.

Parameters: studioId (path), projectId (path), importId (path), X-CSRF-Token (header).

GET /connect/y2kanimator

Browser account confirmation for y2kanimator only. Fixed redirect page.world.y2kanimator:/signin; client_id=y2kanimator; S256 code_challenge and random state required. Unauthenticated users continue through existing web login. POST requires matching Origin and form CSRF, then returns a 90-second one-use authorization code.

Parameters: client_id (query), redirect_uri (query), code_challenge_method (query), code_challenge (query), state (query).

POST /api/v1/native/token

Form-encoded client_id, redirect_uri, code and code_verifier. Atomic one-use S256 exchange, source browser session must remain active. No Cookie, Origin or Sec-Fetch-Site. Returns application/x-plist token and expiresAt; never a browser cookie.

GET /api/v1/native/account

application/x-plist: id (opaque decimal public ID), username, displayName, expiresAt. No email, private account UUID or project data. No Cookie or Origin.

POST /api/v1/native/revoke

Revoke only this native session. No Cookie or Origin. Existing browser logout-all/password reset/session revocation also invalidate native credentials.

POST /api/v1/client-issues

All active accounts can explicitly submit an issue description and optional sanitized client performance recording. Requires exact Origin, CSRF and an idempotency key. Description up to 4000 characters; body up to 512 KiB; server retains only approved diagnostic fields up to 256 KiB. Ten submissions per account per day, bounded global inbox. User-started performance recordings upload automatically on stop using the same authenticated endpoint and an immutable retry key.

Parameters: X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4000
          },
          "recording": {
            "type": [
              "object",
              "null"
            ]
          }
        },
        "required": [
          "description"
        ]
      }
    }
  }
}
GET /api/v1/admin/client-issues

Site administrators only. Newest first, 50 reports per page; use before cursor. Excludes recording bodies.

Parameters: before (query).

GET /api/v1/admin/client-issues/{id}

Site administrators only. Description and optional sanitized diagnostic recording.

Parameters: id (path).

PATCH /api/v1/admin/client-issues/{id}

Site administrators only. Mark a report open or resolved.

Parameters: id (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "status": {
            "enum": [
              "open",
              "resolved"
            ]
          }
        },
        "required": [
          "status"
        ]
      }
    }
  }
}
GET /api/v1/me/activity/snapshot

Initial or explicitly refreshed activity snapshot, limited to six per account per minute. Up to 200 visible channel cursors and 50 unread mentions/replies. Channel unread is a 0/1 activity flag, not a message count. Rechecks current channel visibility; the retired /me/activity returns 410 without database access.

POST /api/v1/channels/{channelId}/read

Monotonic read position bounded by the channel last message number. Current visibility required.

Parameters: channelId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "number": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "number"
        ]
      }
    }
  }
}
POST /api/v1/channels/{channelId}/toys

Trusted two-player Shared puck or Standoff invitation. Ten seconds for an open invitation; optional target principal ID reserves a 15-second challenge. One active toy per channel, two-minute maximum session. Current posting rights and a 16–128-character idempotency key required. Returns 201 on creation, 200 on repeat, 409 while another toy is active. This bounded JSON prototype is not a generic medium-code runtime.

Parameters: channelId (path), X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "kind": {
            "enum": [
              "puck",
              "standoff"
            ]
          },
          "target": {
            "type": "string"
          }
        },
        "required": []
      }
    }
  }
}
POST /api/v1/channels/{channelId}/toys/respond

Accept or decline an ephemeral invitation. Targeted invitations are recipient-only; current posting access is required. Expired invitations return 409. Accepted response includes the community and channel to open.

Parameters: channelId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "action": {
            "enum": [
              "join",
              "decline"
            ]
          }
        },
        "required": [
          "id",
          "action"
        ]
      }
    }
  }
}
GET /api/v1/me/toys/socket

Same-origin authenticated receive-only WebSocket. Delivers transient, recipient-scoped challenge notices across app views; no durable queue, history or gameplay payload.

GET /api/v1/channels/{channelId}/toys/socket

WebSocket Upgrade with current session, channel visibility and exact application Origin. Server sends state snapshots and update deltas; clients send bounded join/decline/grab/move/release/end/fire/duel-move commands, with connection identity and monotonically increasing seq. Acks reconcile local predictions; ping/pong estimates clock offset. Permission leases last at most one second. Only current posting participants may control a live toy. See docs/architecture/chat-toys.md.

Parameters: channelId (path).

GET /api/v1/me/entitlements

Effective Free/Indie/Studio plan, test-grant expiry, site role and personal capabilities. No payments.

GET /api/v1/me/user

Versioned public fields for the signed-in user. Not a downloadable .user codec or importable authority.

GET /api/v1/worlds/{worldId}

Typed World descriptor, navigation and active Studio sponsorship; member access required. Not a downloadable .world codec.

Parameters: worldId (path).

GET /api/v1/applications/y2kanimator/access

Personal capabilities and joined Studios. Optional project query returns current scoped read/edit/full-tool permissions. A sponsored Free artist receives full project tools; personal entitlements do not change. Native token exchange is not implemented.

Parameters: project (query).

GET /api/v1/admin/users

Site admins only. Up to 50 users, with q substring search and after username cursor.

PATCH /api/v1/admin/users/{principalId}/access

Site admins assign test plans and site roles with optimistic version, expiry and audited reason. Reject self-demotion and removal of the last active admin.

Parameters: principalId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer"
          },
          "plan": {
            "enum": [
              "free",
              "indie",
              "studio"
            ]
          },
          "siteRole": {
            "enum": [
              "user",
              "moderator",
              "admin"
            ]
          },
          "expiresAt": {
            "type": [
              "integer",
              "null"
            ]
          },
          "reason": {
            "type": "string"
          }
        },
        "required": [
          "version",
          "plan",
          "siteRole",
          "reason"
        ]
      }
    }
  }
}
GET /api/v1/admin/audit

Site admins only. Latest 50 access changes; before sequence cursor.

GET /api/v1/communities/{communityId}/studio-projects/{projectId}/mediums

Project readers list up to 200 document summaries.

Parameters: communityId (path), projectId (path).

POST /api/v1/communities/{communityId}/studio-projects/{projectId}/mediums

Artists and managers create project-owned Script, Notebook, Scrapbook or Storyboard documents. Paper defaults are resolved once. Creation is idempotent.

Parameters: communityId (path), projectId (path), X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "type": {
            "enum": [
              "page.script",
              "page.notebook",
              "page.scrapbook",
              "page.storyboard"
            ]
          },
          "title": {
            "type": "string"
          },
          "paper": {
            "type": "object"
          }
        },
        "required": [
          "type",
          "title"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/studio-projects/{projectId}/mediums/{mediumId}

Read the current document with current project authorization.

Parameters: communityId (path), projectId (path), mediumId (path).

PATCH /api/v1/communities/{communityId}/studio-projects/{projectId}/mediums/{mediumId}

Artists and managers save using the expected document revision and idempotency key. The update and immutable snapshot commit together. Stale edits and receipts superseded by another edit return 409.

Parameters: communityId (path), projectId (path), mediumId (path), X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "document": {
            "type": "object"
          }
        },
        "required": [
          "document"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/studio-projects/{projectId}/mediums/{mediumId}/export

Download exact stored .page bytes for a saved revision. References remain references; this does not bundle external media or grant access to targets.

Parameters: communityId (path), projectId (path), mediumId (path), revision (query).

GET /api/v1/mediums/head

Explicitly discover a newer saved reference. Both the pinned target and latest target require current authorization; reading never silently updates an embed.

Parameters: reference (query).

POST /api/v1/communities/{communityId}/studio-projects/{projectId}/medium-imports

Import a Script, Notebook, Scrapbook or Storyboard into a fresh project-owned identity. Accepts .page or PAGEPK01 .pagepack; maximum 32 MiB and 64 resources, 128 MiB imports per project. Original bytes are retained; included references are remapped, external links remain explicit. Current artist/manager permissions and idempotency apply.

Parameters: communityId (path), projectId (path), X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/vnd.world.page-package": {
      "schema": {
        "type": "string",
        "format": "binary"
      }
    },
    "application/vnd.world.page": {
      "schema": {
        "type": "string",
        "format": "binary"
      }
    }
  }
}
GET /api/v1/communities/{communityId}/studio-projects/{projectId}/medium-sources

Current project readers discover installed recovered native storyboard/audio sources. These are references to original bytes, not a new timeline codec.

Parameters: communityId (path), projectId (path).

GET /api/v1/medium-imports/{importId}/files/{key}

Read an exact checksum-verified packaged source under current destination project authorization.

Parameters: importId (path), key (path).

GET /api/v1/mediums/resolve

Resolve a pinned MediumReference through installed application adapters. Project documents, Development, project/episode containers and individual chat messages return framed Protobuf; existing y2k asset identities return presentation metadata. Target permissions are independent of the referring document. Document revisions use immutable snapshots; chat revisions use existing events, with deletion erasing history. Unknown or unavailable revisions return 409, never newer content. Unsupported address adapters return 422.

Parameters: reference (query).

GET /api/v1/communities/{communityId}/studio-projects/{projectId}/ideas

Project readers receive bounded idea summaries. Development/Approved/Shelved are independent of episode stages.

Parameters: communityId (path), projectId (path).

POST /api/v1/communities/{communityId}/studio-projects/{projectId}/ideas

Project artists and managers create loose ideas. Does not create an episode. Idempotent; up to 200 ideas per project.

Parameters: communityId (path), projectId (path), X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "document": {
            "type": "object"
          }
        },
        "required": [
          "title"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/studio-projects/{projectId}/ideas/{ideaId}

Read an outline and reusable post-it note documents; current project access required.

Parameters: communityId (path), projectId (path), ideaId (path).

PATCH /api/v1/communities/{communityId}/studio-projects/{projectId}/ideas/{ideaId}

Explicit versioned save, 512 KiB maximum. Artists edit; managers approve/shelve/restore. Notes retain schemaVersion=1, UUID, text and native brush sample data. Pinning belongs to this host. Media references require sharing authority. No automatic episode conversion.

Parameters: communityId (path), projectId (path), ideaId (path), X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "enum": [
              "development",
              "approved",
              "shelved"
            ]
          },
          "document": {
            "type": "object"
          }
        },
        "required": [
          "version",
          "title",
          "document"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/animation-projects/{episodeId}/import

Read the derived presentation manifest for an operator-imported native episode. Requires current project membership. Includes a flat shot list, new-format storyboard sheets and beats, animation recipes and private content-hash media references. Native editing is not implemented.

Parameters: communityId (path), episodeId (path).

GET /api/v1/communities/{communityId}/animation-projects/{episodeId}/import/{fileId}

Stream an indexed private file by SHA-256; rechecks project membership before serving cached or ranged content. Native files are explicit gzip downloads.

Parameters: communityId (path), episodeId (path), fileId (path), Range (header).

HEAD /api/v1/communities/{communityId}/animation-projects/{episodeId}/import/{fileId}

Authorized file metadata without a response body.

Parameters: communityId (path), episodeId (path), fileId (path).

GET /api/v1/feed

Read-only chronological curated publications by followed active users. Excludes draft/withdrawn content. Up to 20 posts, byte-bounded keyset pages; before is the previous nextCursor. Publishing writer/editor is not implemented.

Parameters: before (query).

GET /api/v1/users/{principalId}

Signed-in access to public ID, username and displayName only; no email/private UUID.

Parameters: principalId (path).

GET /api/v1/users/{principalId}/follow

Current caller follow state.

Parameters: principalId (path).

PUT /api/v1/users/{principalId}/follow

Idempotent follow, maximum 5000, rejects self-follow.

Parameters: principalId (path), X-CSRF-Token (header).

DELETE /api/v1/users/{principalId}/follow

Remove caller follow relationship only.

Parameters: principalId (path), X-CSRF-Token (header).

GET /api/v1/channels/{channelId}/reactions

Read up to 50 comma-separated post IDs. Rechecks content access.

Parameters: channelId (path), ids (query).

PUT /api/v1/channels/{channelId}/reactions/{postId}

Idempotent emoji reaction from the shared inventory allowlist; maximum 8 per caller/post and 20 distinct per post.

Parameters: channelId (path), postId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "emoji": {
            "type": "string"
          }
        },
        "required": [
          "emoji"
        ]
      }
    }
  }
}
DELETE /api/v1/channels/{channelId}/reactions/{postId}

Remove only the caller reaction for this emoji.

Parameters: channelId (path), postId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "emoji": {
            "type": "string"
          }
        },
        "required": [
          "emoji"
        ]
      }
    }
  }
}
GET /api/v1/publications/reactions

Read up to 50 comma-separated post IDs. Rechecks content access.

Parameters: ids (query).

PUT /api/v1/publications/reactions/{postId}

Idempotent emoji reaction from the shared inventory allowlist; maximum 8 per caller/post and 20 distinct per post.

Parameters: postId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "emoji": {
            "type": "string"
          }
        },
        "required": [
          "emoji"
        ]
      }
    }
  }
}
DELETE /api/v1/publications/reactions/{postId}

Remove only the caller reaction for this emoji.

Parameters: postId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "emoji": {
            "type": "string"
          }
        },
        "required": [
          "emoji"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/assigned-work

Current caller’s unfinished assigned episode deliverables and shot tasks, filtered by current Studio and project access. Compact summaries only, 50 items per page; nextOffset is null at the end. Completed, locked and retired work is excluded.

Parameters: communityId (path), offset (query).

GET /health/live

Worker liveness only.

GET /health/ready

D1 check, private storage binding and scheduled maintenance heartbeat. 503 if missing, failed or over one hour old.

GET /api/v1/media

Owner storage usage, limits and accepted formats.

POST /api/v1/media

Reserve space atomically: 8 MiB/file, 100 MiB/account, 512 MiB/test service, 500 items/account; preview reservation counts toward quota. Idempotent per account. Upload originals within one hour.

Parameters: X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "mime": {
            "enum": [
              "image/png",
              "image/jpeg",
              "image/gif",
              "image/webp",
              "application/vnd.world.y2k-object"
            ]
          },
          "bytes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 8388608
          }
        },
        "required": [
          "name",
          "mime",
          "bytes"
        ]
      }
    }
  }
}
GET /api/v1/media/trash

Owner uploads recoverable within seven days.

PUT /api/v1/media/{mediaId}

Owner supplies original raster or registered .y2k object bytes. Object signature, SHA-256 envelope, version, bounded Protobuf graph, type/filename and native model references are structurally validated. Native renderer execution is not supported. Pinned SHA-256 revision, private R2 object and saved inventory reference.

Parameters: mediaId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/octet-stream": {
      "schema": {
        "type": "string",
        "format": "binary"
      }
    }
  }
}
DELETE /api/v1/media/{mediaId}

Owner revokes media access immediately; bytes retained for seven-day restore and still count against quota.

Parameters: mediaId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {},
        "required": []
      }
    }
  }
}
GET /api/v1/media/{mediaId}/source

Current authorization is checked on every request. Original image bytes, private/no-store; no bearer URL or public bucket. GIF bytes remain unchanged.

Parameters: mediaId (path).

HEAD /api/v1/media/{mediaId}/source

Same authorization as GET; no response body.

Parameters: mediaId (path).

GET /api/v1/media/{mediaId}/preview

Authorized preview; GIF always returns original animation.

Parameters: mediaId (path).

PUT /api/v1/media/{mediaId}/preview

Owner supplies optional WebP up to 512 pixels per side and 128 KiB; GIFs skip static thumbnails.

Parameters: mediaId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "image/webp": {
      "schema": {
        "type": "string",
        "format": "binary"
      }
    }
  }
}
POST /api/v1/media/{mediaId}/restore

Owner restores a trashed upload before expiry; same id/revision and existing authorized references.

Parameters: mediaId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {},
        "required": []
      }
    }
  }
}
GET /api/v1/auth/sessions

Current account sessions with non-secret ids, expiry and current-session flag.

DELETE /api/v1/auth/sessions/{sessionId}

Revoke another session owned by this account. Use logout for the current session.

Parameters: sessionId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {},
        "required": []
      }
    }
  }
}
GET /api/v1/communities/{communityId}/moderation

Owner/admin lists active timeouts and bans.

Parameters: communityId (path).

POST /api/v1/communities/{communityId}/moderation

Owner/admin moderation with reason and hierarchy checks. Timeout blocks posting, ban revokes membership/grants and prevents rejoining. Unban does not restore membership. Changes audited.

Parameters: communityId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "principalId": {
            "type": "string"
          },
          "action": {
            "enum": [
              "timeout",
              "clear-timeout",
              "ban",
              "unban"
            ]
          },
          "seconds": {
            "type": "integer",
            "minimum": 60,
            "maximum": 604800
          },
          "reason": {
            "type": "string",
            "maxLength": 300
          }
        },
        "required": [
          "principalId",
          "action",
          "reason"
        ]
      }
    }
  }
}
DELETE /api/v1/communities/{communityId}/invitations/{invitationId}

Owner/admin revokes an invitation by its non-bearer list identifier; audited.

Parameters: communityId (path), invitationId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {},
        "required": []
      }
    }
  }
}
GET /api/v1/community-entry

Public join-page metadata by community handle, id or invitation. Private Communities require membership or a valid invitation; no channel data is returned to nonmembers. Handle lookup and short invitation codes are case-insensitive.

Parameters: community (query), id (query), invite (query), destination (query).

GET /api/v1/communities/{communityId}/addresses

Member-only canonical community and visible channel/Board addresses.

Parameters: communityId (path).

PATCH /api/v1/communities/{communityId}/addresses

Owner/admin rename with case-insensitive uniqueness and retained aliases. Body: handle, optional kind (community/channel/board) and destination id.

Parameters: communityId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {},
        "required": []
      }
    }
  }
}
GET /api/v1/discovery

Signed-in directory of discoverable, publicly joinable servers, newest first. Only id/name/tags, member count and viewer role are returned. Banned destinations are omitted. Up to 48 items plus nextCursor; pass after for the next page.

Parameters: after (query).

POST /api/v1/communities/{communityId}/join

Join a publicly joinable server without an invitation as a contributor. Idempotent for existing members, preserving their role. Bans and the 100-server join limit remain enforced. Rejoining a revoked membership clears old restricted-channel grants and elevated roles. Joining is audited.

Parameters: communityId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {},
        "required": []
      }
    }
  }
}
GET /api/v1/config

Public-to-testers environment and sign-in configuration.

GET /api/v1/test-content

Public, read-only iPad test catalogue. Global snapshot, native pack identities and content-addressed detail/original URLs; no ownership transfer, upload or editing. Temporary asset storage, separate from private Studio data.

GET /api/v1/me/inventory/studio-resources

Browse currently authorized project resources without copying content or granting access. Without project, lists accessible projects. upload=1 narrows that list to current upload authority and makes the selected-project response a bounded identity/capability lookup. Otherwise, project returns a filtered 80-item page of documents, Development, notes, native episode files and prepared shot/track/actor/symbol entries.

Parameters: project (query), upload (query), kind (query), offset (query).

GET /api/v1/studio-resources/{resourceId}/source

Stream exact immutable native object bytes from a private R2 bundle under current project authorization. Inventory saving and chat sharing never grant target access.

Parameters: resourceId (path).

GET /api/v1/me/inventory

Personal saved test-pack and individual content references, favourites and collections. Always scoped to the authenticated account; does not grant copyright or paid entitlements. Accept application/vnd.world.page returns a principal-scoped envelope and up to 100 entries. Continue with nextCursor; 409 inventory_changed requires restarting the snapshot.

Parameters: cursor (query).

GET /api/v1/content/resolve

Resolve a stable content identity at an exact immutable revision. Private uploads require a signed-in owner or currently authorized conversation recipient. Unknown identities return 404; unavailable revisions return 409, never silently the latest. This endpoint does not grant ownership.

Parameters: packId (query), itemId (query), revision (query).

POST /api/v1/me/inventory/references

Idempotently save a server-resolved reference to personal inventory. Shared MediumReferences, published test content and currently accessible private uploads are supported; saving is not a purchase, license transfer or permanent access grant.

Parameters: X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "ref": {
            "type": "object",
            "description": "Legacy AssetReference or shared MediumReference."
          }
        },
        "required": [
          "ref"
        ]
      }
    }
  }
}
PATCH /api/v1/me/inventory/references/{key}

Set favourite/collection, or explicitly update a shared saved reference with updateRevision and expectedRevision. Current target permissions and a compare-and-swap check apply.

Parameters: X-CSRF-Token (header), key (path).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "favourite": {
            "type": "boolean"
          },
          "collectionId": {
            "type": [
              "string",
              "null"
            ]
          },
          "updateRevision": {
            "type": "boolean"
          },
          "expectedRevision": {
            "type": "string"
          }
        },
        "required": []
      }
    }
  }
}
DELETE /api/v1/me/inventory/references/{key}

Remove a shared reference from this inventory only; never delete the target.

Parameters: X-CSRF-Token (header), key (path).

POST /api/v1/me/inventory/test-items

Idempotently add a server-validated public test pack. Paid acquisitions are not implemented.

Parameters: X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "packId": {
            "type": "string"
          }
        },
        "required": [
          "packId"
        ]
      }
    }
  }
}
POST /api/v1/me/inventory/collections

Create a personal collection; duplicate names return the existing collection. Maximum 100.

Parameters: X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          }
        },
        "required": [
          "name"
        ]
      }
    }
  }
}
PATCH /api/v1/me/inventory/items/{packId}

Set favourite and/or collection. Both item and collection must belong to this account.

Parameters: X-CSRF-Token (header), packId (path).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "favourite": {
            "type": "boolean"
          },
          "collectionId": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": []
      }
    }
  }
}
DELETE /api/v1/me/inventory/collections/{collectionId}

Remove only the organization container; retain items in All items. Send an empty JSON object.

Parameters: X-CSRF-Token (header), collectionId (path).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {},
        "required": []
      }
    }
  }
}
GET /api/v1/communities/{studioId}/mentions

Search up to twenty active Community members by username/display-name prefix. Membership required; no notifications are sent.

Parameters: studioId (path), q (query).

POST /api/v1/link-preview

Bounded public HTTPS title/description preview. Requires a session and CSRF token; unavailable or disallowed pages return preview:null. No remote scripts or images are loaded.

Parameters: X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2048
          }
        }
      }
    }
  }
}
GET /api/v1/content-types

Versioned content registry: .y2kshot, .y2kactor, .y2ksymbol and .y2ktrack use the experimental Y2KOBJ01 Protobuf profile. The native .y2kmovie/.y2kboards codecs and ZIP .y2k distribution profile remain distinct.

GET /api/v1/session

Current account presentation + CSRF token, or account:null. Never returns the private account UUID.

GET /api/v1/me

Current individual principal.

POST /api/v1/auth/email/start

Send a ten-minute, single-use six-digit code. Generic responses for ineligible addresses; cookie bound, rate limited, maximum five guesses.

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string"
          },
          "purpose": {
            "enum": [
              "signup",
              "reset"
            ]
          }
        },
        "required": [
          "email"
        ]
      }
    }
  }
}
POST /api/v1/auth/email/verify

Verify the code for the browser-bound email challenge. Does not create an account.

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string",
            "pattern": "^[0-9]{6}$"
          }
        },
        "required": [
          "code"
        ]
      }
    }
  }
}
GET /api/v1/auth/verification

Current browser verification status.

POST /api/v1/auth/register

Consume a verified email challenge and create a password account. Username does not allocate a public DNS namespace. Password: 8–128 characters, common-pattern/username rejection, scrypt N=16384/r=8/p=5.

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string"
          },
          "password": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          }
        },
        "required": [
          "username",
          "password"
        ]
      }
    }
  }
}
POST /api/v1/auth/login

Email or username and password; generic failure and rate limits.

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "login": {
            "type": "string"
          },
          "password": {
            "type": "string"
          }
        },
        "required": [
          "login",
          "password"
        ]
      }
    }
  }
}
POST /api/v1/auth/username/available

Check a normalized username without reserving it. Returns username and available only. Origin checked; 60 requests/minute per IP. Registration remains authoritative for concurrent claims.

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string"
          }
        },
        "required": [
          "username"
        ]
      }
    }
  }
}
POST /api/v1/auth/register/username

Create a username/password account without email. Email remains null and recovery unavailable until an optional address is verified. Same password policy and scrypt as verified-email signup. Origin checked, limited to 10 attempts/hour and 30/day per IP. Username does not allocate a public DNS namespace.

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string"
          },
          "password": {
            "type": "string"
          }
        },
        "required": [
          "username",
          "password"
        ]
      }
    }
  }
}
POST /api/v1/auth/recovery/start

Current account with no email: prove current password and send a verification code. Does not attach an address yet or link existing accounts. Bounded account/IP/address delivery limits; ten-minute challenge bound to account and session.

Parameters: X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string"
          },
          "password": {
            "type": "string"
          }
        },
        "required": [
          "email",
          "password"
        ]
      }
    }
  }
}
POST /api/v1/auth/recovery/verify

Consume the session-bound recovery code and atomically attach a verified email to an account that still has no email. Five-attempt limit; unique addresses; no change-email or account linking.

Parameters: X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          }
        },
        "required": [
          "code"
        ]
      }
    }
  }
}
GET /api/v1/auth/security

Current account only: password-set status, Google connection and own email (null for username-only accounts). Never returns hashes or provider credentials.

POST /api/v1/auth/password/reset

Consume a verified reset challenge, change password and revoke every session. Sign in again afterwards.

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "password": {
            "type": "string"
          }
        },
        "required": [
          "password"
        ]
      }
    }
  }
}
POST /api/v1/auth/google/start

Return Google authorization URL with browser-bound state, nonce and PKCE. Only openid/email/profile scopes.

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "invitation": {
            "type": "string"
          }
        },
        "required": []
      }
    }
  }
}
GET /api/v1/auth/google/callback

Validate state, exchange code server-side and verify signed ID token. Existing Google identities sign in; new identities choose a username. Matching email never silently merges accounts.

POST /api/v1/auth/google/complete

Consume verified Google profile and create a first-party account with a username. No world.page password is required; it can be added later through email-verified recovery. Existing Google sign-in remains available.

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string"
          },
          "password": {
            "type": "string"
          },
          "displayName": {
            "type": "string"
          }
        },
        "required": [
          "username"
        ]
      }
    }
  }
}
POST /api/v1/auth/logout

Revoke this server session.

Parameters: X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {},
        "required": []
      }
    }
  }
}
POST /api/v1/auth/logout-all

Revoke all sessions belonging to this account.

Parameters: X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {},
        "required": []
      }
    }
  }
}
GET /api/v1/communities

Owned and active-member Studios only; capped at 100 for testing.

POST /api/v1/communities

Create a Studio with exactly one owner and two default channels. Per-account idempotency; ten owned Studios maximum.

Parameters: X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 80
          },
          "type": {
            "enum": [
              "studio",
              "community"
            ]
          }
        },
        "required": [
          "name"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/page

Authorized framed Protobuf Community root. Contains tags, definition/policy revisions and logical references; definition and navigator have dedicated endpoints; inventory/index logical resolvers remain future work.

Parameters: communityId (path).

GET /api/v1/communities/{communityId}/navigator

Authorized Protobuf navigator configuration. Registered section labels, order and visibility; no executable code or permission changes.

Parameters: communityId (path).

GET /api/v1/communities/{communityId}/definition

Authorized Protobuf definition with versioned navigation settings and discoverability.

Parameters: communityId (path).

PATCH /api/v1/communities/{communityId}/definition

Owner/admin only; checked revision, bounded tags and transactional audit. Tags never grant access. Public joining permits explicit membership requests without invitations. Discovery lists public join pages; invitation-only Communities cannot be listed. Disabling either setting leaves existing memberships intact.

Parameters: communityId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 80
          },
          "tags": {
            "type": "array",
            "maxItems": 8,
            "items": {
              "type": "string",
              "pattern": "^[a-z][a-z0-9-]{0,31}$"
            }
          },
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "discoverable": {
            "type": "boolean"
          },
          "publicJoin": {
            "type": "boolean"
          },
          "navigationConfig": {
            "type": "object",
            "properties": {
              "sections": {
                "type": "array",
                "minItems": 10,
                "maxItems": 10,
                "items": {
                  "type": "object",
                  "required": [
                    "id",
                    "label",
                    "enabled"
                  ],
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "label": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 60
                    },
                    "enabled": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          }
        },
        "required": [
          "name",
          "tags",
          "version"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/workspace

Load an authorized Studio, its visible channels and 50 messages from the selected channel in one response. Optional channel must belong to this Studio and be viewable. Community/channel IDs are 19-digit decimal strings; old Studio routes and legacy IDs are retired. Accept application/vnd.world.page for a bounded Protobuf Workspace frame; the browser uses this transport.

Parameters: communityId (path), channel (query).

GET /api/v1/communities/{communityId}/channels

Only channels the caller may view.

Parameters: communityId (path).

POST /api/v1/communities/{communityId}/channels

Owner/admin only, at most 100 channels per Studio.

Parameters: communityId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "kind": {
            "enum": [
              "text",
              "announcements"
            ]
          },
          "visibility": {
            "enum": [
              "members",
              "restricted"
            ]
          }
        },
        "required": [
          "name"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/studio-projects

Community directory of project names and kinds. Only project members receive cover references, template details and episode counts. Includes six common animation presets and six storyboard layouts. Custom dimensions are capped at QHD: long edge 2560, short edge 1440, with either orientation.

Parameters: communityId (path).

POST /api/v1/communities/{communityId}/studio-projects

Community owner/admin establishes an animation project container and becomes its project owner. Does not create an episode. Project permissions are separate from community roles. Idempotent create.

Parameters: communityId (path), X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "template": {
            "type": "object",
            "description": "schema=1; animation width/height are positive integers with max(width,height)<=2560 and min(width,height)<=1440; storyboard template/paper/dpi/notesFraction/geometryVersion=2"
          },
          "cover": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "schema",
              "packId",
              "itemId",
              "revision"
            ],
            "properties": {
              "schema": {
                "const": 1
              },
              "packId": {
                "type": "string"
              },
              "itemId": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "revision": {
                "type": "string",
                "pattern": "^[a-f0-9]{64}$"
              }
            }
          }
        },
        "required": [
          "name"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/studio-projects/{projectId}

Project-member-only details and episodes. Community admin status does not grant project access.

Parameters: communityId (path), projectId (path).

PATCH /api/v1/communities/{communityId}/studio-projects/{projectId}

Project owner/admin/manager only. Requires current project version. Changes the default for future episodes; existing episode settings remain unchanged. Template version advances only when validated template changes. QHD limits apply to custom dimensions too.

Parameters: communityId (path), projectId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "template": {
            "type": "object"
          },
          "cover": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "schema",
              "packId",
              "itemId",
              "revision"
            ],
            "properties": {
              "schema": {
                "const": 1
              },
              "packId": {
                "type": "string"
              },
              "itemId": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "revision": {
                "type": "string",
                "pattern": "^[a-f0-9]{64}$"
              }
            }
          }
        },
        "required": [
          "version",
          "name",
          "template"
        ]
      }
    }
  }
}
POST /api/v1/communities/{communityId}/studio-projects/{projectId}/episodes

Project managers create an episode in Development. Project Settings snapshots the parent template; Custom validates and snapshots the supplied episode-only template. Neither changes the parent or existing documents. Atomically links the episode. Requires current project version, a template within QHD limits, and an idempotency key. Returns the existing animation workflow ID; maximum 100 episodes per project.

Parameters: communityId (path), projectId (path), X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "maxLength": 600
          },
          "settingsMode": {
            "enum": [
              "project",
              "custom"
            ]
          },
          "template": {
            "type": "object",
            "description": "Required for custom mode; same schema as project templates."
          },
          "cover": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "schema",
              "packId",
              "itemId",
              "revision"
            ],
            "properties": {
              "schema": {
                "const": 1
              },
              "packId": {
                "type": "string"
              },
              "itemId": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "revision": {
                "type": "string",
                "pattern": "^[a-f0-9]{64}$"
              }
            }
          }
        },
        "required": [
          "version",
          "name"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/studio-projects/{projectId}/members

Project owner/admin only; public profile identities, explicit project roles and project version.

Parameters: communityId (path), projectId (path).

PUT /api/v1/communities/{communityId}/studio-projects/{projectId}/members

Versioned, audited project role update. Owner/admin may manage managers/artists/viewers; only project owner may grant/change admin. The owner cannot be removed. Target must be an active community member. Community membership admits access but never supplies project-management authority.

Parameters: communityId (path), projectId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer"
          },
          "principalId": {
            "type": "string"
          },
          "role": {
            "enum": [
              "admin",
              "manager",
              "artist",
              "viewer"
            ]
          },
          "state": {
            "enum": [
              "active",
              "revoked"
            ]
          }
        },
        "required": [
          "version",
          "principalId",
          "role",
          "state"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/animation-projects

Lists up to 100 episode workflow summaries visible to the current project member. Parent containers are listed through studio-projects.

Parameters: communityId (path).

POST /api/v1/communities/{communityId}/animation-projects

Retired unparented creation endpoint. Returns 409 project_container_required; create an episode through studio-projects/{projectId}/episodes.

Parameters: communityId (path).

GET /api/v1/communities/{communityId}/animation-projects/{projectId}

Project-member-only episode state, pinned template, public producer/assignee identities and latest 40 events. Shot occurrence IDs are distinct from content IDs. This JSON management API does not change the .page Protobuf transport or native .y2k formats.

Parameters: communityId (path), projectId (path).

POST /api/v1/communities/{communityId}/animation-projects/{projectId}/commands

Version-checked, idempotent workflow transaction with atomic event history. Project-manager-only set-stage/deliverable/advance/add-shot/review/assign/unassign/reopen-shot/episode-cover. Community admin status alone grants none of these permissions. Contributors claim/release/submit only their assigned work. Managers assign pre-production tasks; assigned contributors and managers may update primary progress states. target-status atomically updates the canonical deliverables for an overview target; managers or artists assigned to every constituent can update unlocked work. Progress Done does not approve or lock work. Approved deliverables must be reopened before progress changes. New episodes allow Outline, Script and Storyboard work immediately. Outline, Script and Storyboard require sign-off before Audio and Timing; these require sign-off before animation shots, followed by PostFX and Export. Legacy flexible episodes retain their existing access. target-review signs off or reopens a target; empty work cannot be approved. Managers use set-stage to move directly or reopen a completed episode. Stage changes do not imply deliverable approval. One task represents the whole shot; acceptance locks the shot. Legacy pass submissions remain preserved as history. Reopening a shot requires a reason and preserves the current stage and unrelated reviews. Bounties are immutable recorded offers in minor currency units; no payment settlement or native editing is performed. Omit fields unrelated to the chosen action.

Parameters: communityId (path), projectId (path), X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "action": {
            "enum": [
              "deliverable",
              "advance",
              "add-shot",
              "claim",
              "release",
              "submit",
              "review",
              "unassign",
              "reopen-shot",
              "assign",
              "episode-cover",
              "episode-description",
              "shot-status",
              "preproduction-status",
              "preproduction-assign",
              "set-stage",
              "target-status",
              "target-review"
            ]
          },
          "stage": {
            "enum": [
              "development",
              "pre-production",
              "production",
              "post"
            ]
          },
          "target": {
            "enum": [
              "outline",
              "script",
              "storyboard",
              "audio-timing",
              "postfx",
              "export"
            ]
          },
          "step": {
            "type": "string"
          },
          "status": {
            "enum": [
              "todo",
              "in-progress",
              "in-review",
              "done"
            ]
          },
          "description": {
            "type": "string",
            "maxLength": 600
          },
          "notes": {
            "type": "string",
            "maxLength": 8000
          },
          "writing": {
            "type": "object",
            "description": "Validated version-1 writing blocks for Outline and Script; plain text must match notes."
          },
          "accepted": {
            "type": "boolean"
          },
          "refs": {
            "type": "array",
            "maxItems": 8,
            "items": {
              "type": "object",
              "required": [
                "schema",
                "packId",
                "itemId",
                "revision"
              ],
              "properties": {
                "schema": {
                  "const": 1
                },
                "packId": {
                  "type": "string"
                },
                "itemId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "revision": {
                  "type": "string",
                  "pattern": "^[a-f0-9]{64}$"
                }
              }
            }
          },
          "cover": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "schema",
              "packId",
              "itemId",
              "revision"
            ],
            "properties": {
              "schema": {
                "const": 1
              },
              "packId": {
                "type": "string"
              },
              "itemId": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "revision": {
                "type": "string",
                "pattern": "^[a-f0-9]{64}$"
              }
            }
          },
          "principalId": {
            "type": "string"
          },
          "shotId": {
            "type": "string"
          },
          "taskId": {
            "enum": [
              "shot"
            ]
          },
          "accept": {
            "type": "boolean"
          },
          "reason": {
            "type": "string",
            "maxLength": 2000
          },
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "scene": {
            "type": "string",
            "maxLength": 100
          },
          "frames": {
            "type": "integer",
            "minimum": 1,
            "maximum": 2000000
          },
          "brief": {
            "type": "string",
            "maxLength": 2000
          },
          "currency": {
            "enum": [
              "USD",
              "EUR",
              "GBP",
              "PLN"
            ]
          },
          "bounties": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "shot": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100000000
              }
            }
          }
        },
        "required": [
          "version",
          "action"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/projects

Owner and active Studio admins only until project assignments exist. Returns up to 100 private workflow records and phase definitions.

Parameters: communityId (path).

POST /api/v1/communities/{communityId}/projects

Create an animation workflow in Development. Only a name is accepted; phases cannot be skipped. Idempotency is per Studio and creating account. No authored content is uploaded.

Parameters: communityId (path), X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100
          }
        },
        "required": [
          "name"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/projects/{projectId}

Owner/admin-only project metadata, phase checklists and recent approval history. Project IDs are 19-digit decimal strings.

Parameters: communityId (path), projectId (path).

PATCH /api/v1/communities/{communityId}/projects/{projectId}/checks

Owner/admin marks one item in the current phase. Previous and future phases and completed projects are read-only. Version conflicts return 409; this is manual workflow sign-off, not verification of uploaded artwork.

Parameters: communityId (path), projectId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "step": {
            "enum": [
              "outline",
              "sketches",
              "script",
              "storyboard",
              "audio",
              "timing",
              "animatic",
              "animation",
              "postfx",
              "completion"
            ]
          },
          "done": {
            "type": "boolean"
          }
        },
        "required": [
          "version",
          "step",
          "done"
        ]
      }
    }
  }
}
POST /api/v1/communities/{communityId}/projects/{projectId}/approve

Studio owner only. Requires every current-phase item to be checked and the exact current version/phase. Development opens Pre-Production; Pre-Production opens Production; Production approval completes the project. SQL mutation and approval history are atomic.

Parameters: communityId (path), projectId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "phase": {
            "enum": [
              "development",
              "pre-production",
              "production"
            ]
          }
        },
        "required": [
          "version",
          "phase"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/members

Members of an accessible Studio; no private account IDs.

Parameters: communityId (path).

PATCH /api/v1/communities/{communityId}/members/{principalId}

Owner/admin only. Only owners can manage admins. Owner cannot be removed through membership changes.

Parameters: communityId (path), principalId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "role": {
            "enum": [
              "admin",
              "contributor",
              "reviewer",
              "guest"
            ]
          },
          "state": {
            "enum": [
              "active",
              "revoked"
            ]
          }
        },
        "required": [
          "role",
          "state"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/invitations

Owner/admin lists invitation identifiers, roles, expiry, reusable status and join counts; bearer tokens are never returned.

Parameters: communityId (path).

POST /api/v1/communities/{communityId}/invitations

Owner/admin creates an invitation. Set reusable=true for a seven-character root-domain link that multiple accounts can use until revoked; otherwise a single-use 48-hour link. No email is sent. Invitees sign in with their own account.

Parameters: communityId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "role": {
            "enum": [
              "contributor",
              "reviewer",
              "guest"
            ]
          },
          "reusable": {
            "type": "boolean"
          }
        },
        "required": []
      }
    }
  }
}
POST /api/v1/invitations/accept

Accept a short reusable code or a legacy single-use token. Reusable joins preserve active roles, clear stale restricted grants on rejoin, enforce bans and join limits, and are audited. Legacy single-use replay remains rejected.

Parameters: X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string"
          }
        },
        "required": [
          "token"
        ]
      }
    }
  }
}
GET /api/v1/communities/{communityId}/audit

Owner/admin only; latest 100 membership/grant events. Not yet a complete lifecycle audit.

Parameters: communityId (path).

GET /api/v1/channels/{channelId}/typing

Other active typists in this channel. Requires current visibility; rechecks typist membership, post permission, session and timeout. Excludes self. Maximum ten profiles; hints expire after eight seconds.

Parameters: channelId (path).

POST /api/v1/channels/{channelId}/typing

Publish or clear this session’s activity hint. No draft text is stored. Active hints require post permission. Limited to 60 changes per account per minute.

Parameters: channelId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "active": {
            "type": "boolean"
          }
        },
        "required": [
          "active"
        ]
      }
    }
  }
}
GET /api/v1/channels/{channelId}/messages

With Accept application/vnd.world.page, returns one Snapshot Frame, at most 50 posts/events under the byte budget. No cursor requests latest snapshot; before is a room-local post number; after is a committed room change cursor. Cursors and post numbers are exact decimal strings. History must not advance the live cursor. JSON compatibility uses the older global sequence; do not mix cursor namespaces.

Parameters: channelId (path), before (query), after (query).

POST /api/v1/channels/{channelId}/messages

Rechecks posting permission in SQL. Read-only roles cannot post; announcements require owner/admin. Repeated idempotency key returns the same message when text and normalized references match. Requires non-empty text or 1–8 references; references are resolved server-side. History and workspace messages include content references. Content-Type application/vnd.world.page accepts exactly one PostCommand Frame for this Community (32 KiB maximum). The browser sends binary commands; response is a binary Receipt when requested. Edits/deletions are separate JSON commands.

Parameters: channelId (path), X-CSRF-Token (header), Idempotency-Key (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "body": {
            "type": "string",
            "maxLength": 4000
          },
          "contentRefs": {
            "type": "array",
            "maxItems": 8,
            "items": {
              "type": "object",
              "required": [
                "schema",
                "packId",
                "itemId",
                "revision"
              ],
              "properties": {
                "schema": {
                  "const": 1
                },
                "packId": {
                  "type": "string"
                },
                "itemId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "revision": {
                  "type": "string",
                  "pattern": "^[a-f0-9]{64}$"
                }
              }
            }
          }
        },
        "required": []
      }
    },
    "application/vnd.world.page": {
      "schema": {
        "type": "string",
        "format": "binary"
      }
    }
  }
}
PATCH /api/v1/channels/{channelId}/messages/{messageId}

Author with current posting access edits the text at the expected revision. Generates a new committed change; original message number stays fixed.

Parameters: channelId (path), messageId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "body": {
            "type": "string",
            "minLength": 1,
            "maxLength": 4000
          }
        },
        "required": [
          "version",
          "body"
        ]
      }
    }
  }
}
DELETE /api/v1/channels/{channelId}/messages/{messageId}

Author or owner/admin with posting access. Requires current revision; erases current and prior event payloads and emits a numbered tombstone.

Parameters: channelId (path), messageId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "minimum": 1
          }
        },
        "required": [
          "version"
        ]
      }
    }
  }
}
GET /api/v1/channels/{channelId}/grants

Owner/admin only.

Parameters: channelId (path).

PUT /api/v1/channels/{channelId}/grants

Owner/admin only. Restricted-channel view and post grant; post requires view. Roles and active membership remain upper bounds.

Parameters: channelId (path), X-CSRF-Token (header).

Request schema
{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "principalId": {
            "type": "string"
          },
          "view": {
            "type": "boolean"
          },
          "post": {
            "type": "boolean"
          }
        },
        "required": [
          "principalId",
          "view",
          "post"
        ]
      }
    }
  }
}