> ## Documentation Index
> Fetch the complete documentation index at: https://docs.alakazam.gg/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a world (generate or import)

> Two modes, selected by the body. **Generate** (default): produce a playable SMWorld from a `premise` and/or seed frame — or from a chapter/book excerpt via `text` (book-to-game) — reserving one generation against your daily quota before spending GPU. **Import**: pass a compiled `world` object to persist it VERBATIM (no generation/GPU) — the graph is schema-validated but not recompiled, and it returns `201` with `imported:true`. Import still reserves one `generation` of quota (anti-spam) and is bounded in size (see `413`). Worlds created with a **live** key are attributed to your account and appear in your web Studio under **My Creations** (test-mode creations stay out of the Studio list).




## OpenAPI

````yaml /alakazam-v1.yaml post /v1/worlds
openapi: 3.0.3
info:
  title: 'Alakazam: Programmable Worlds API'
  version: '1.0'
  description: >
    **Alakazam is the programmable worlds API.** Generate playable, AI-rendered
    worlds from a prompt or an image, program their logic, and embed them in
    your own products and games.


    A world is *programmable*: a live graph of states and events you generate,
    then read, edit, fork, drive, and react to through the API. Two surfaces: a
    **Creation API** (generate, read, manage, fork worlds) and a **Runtime/Embed
    API** (mint short-lived session tokens your end-users' browsers use to boot
    an embedded world).


    **Authentication.** Two schemes. Management endpoints (`/v1/apps*`) use your
    Supabase user session. Data endpoints use an **API key** issued per app:
    `pk_…` (publishable, browser-safe, read-only) and `sk_…` (secret,
    server-only — create/edit worlds and mint session tokens). Embedding a world
    in a browser uses a short-lived **session token** minted server-side with a
    secret key (not a publishable key directly). Never ship a secret key to a
    browser.


    **Test vs live.** Keys come in `test` and `live` modes — the prefix tells
    you which (`sk_test_…`/`pk_test_…` vs `sk_live_…`/`pk_live_…`). A **test**
    key runs against a sandbox: every generative endpoint returns a
    deterministic mock marked `"mock": true`, with no GPU or vendor spend; test
    worlds/characters are isolated from live data (forced `private`, never
    slugged or discoverable); and test usage is **never** billed. See the
    Testing guide.


    **Usage, quota & billing.** Every operation is counted against a per-app
    daily quota, reserved before any GPU spend. Exceeding it returns `402`. The
    quota is a free abuse guard, not a charge. Billing, when enabled, is
    **runtime-only**: you pay for `session_seconds` (live play time). Creating
    worlds and every other operation are free. Test-mode usage is never billed,
    even after billing is enabled. The API is in developer preview. See Pricing.


    **Building with an AI coding agent?** Install the skill (`npx skills add -g
    https://docs.alakazam.gg/skill.md`) and the MCP server (`npx
    @alakazamworld/mcp`) so your agent knows this API and can call it live. See
    the Agent quickstart.
servers:
  - url: https://api.alakazam.gg
    description: Production (placeholder, set to your conjure-service host)
security: []
tags:
  - name: Apps & Keys
    description: >-
      Create apps (tenants) and manage API keys. Authenticated with your user
      session.
  - name: Worlds
    description: >-
      Create, read, manage, and fork SMWorld games. Authenticated with an API
      key.
  - name: Graph editing
    description: >
      Read and program a world's graph of states (nodes), events (edges), and
      the entrance, using deterministic CRUD, a batch op vocabulary, a
      natural-language kernel-agent edit, and the kernel validate/lint gate.
      Every write is validated fail-closed before it persists. Authenticated
      with an API key.
  - name: Versions
    description: >
      Snapshot, branch, check out, and diff a world's graph. Versions form a
      branching tree of full snapshots; a HEAD pointer tracks the working graph.
      Authenticated with an API key.
  - name: Characters
    description: >
      Create, manage, and talk to characters: a SMWorld subtype that pairs a
      stance-graph with a "brain" (persona, lore, voice). CRUD is authenticated
      with an API key. The live talk turn (/say) and voice (/tts) are called
      from the browser with a short-lived session token.
  - name: Scenario Studio
    description: >
      Author variation/counterfactual plans over an episode or scenario, submit
      them as durable batches (N verified clips), poll them, and accept/reject
      each result. Nothing bills at submit — a clip is charged only when
      accepted; rejected and failed clips never touch the ledger. Authenticated
      with an API key.
  - name: Sessions
    description: Mint short-lived runtime tokens for embedding a world.
  - name: Usage
    description: Per-app usage and quota.
  - name: Webhooks
    description: >-
      Register HTTPS endpoints to receive signed server-side event
      notifications. Managed with your user session.
  - name: Simulation & Data
    description: >
      **Beta — self-hosted runner.** Drive a world headlessly as a training
      environment (gym) and stream the SNN-controller observation contract: two
      virtual proximity sensors, collision spikes, object labels, and an
      optional square RGB camera. The same schema is emitted offline by the
      dataset exporter (JSONL episodes + train-ready NPZ), so controllers
      trained on recorded data plug straight into the live loop.
paths:
  /v1/worlds:
    post:
      tags:
        - Worlds
      summary: Create a world (generate or import)
      description: >
        Two modes, selected by the body. **Generate** (default): produce a
        playable SMWorld from a `premise` and/or seed frame — or from a
        chapter/book excerpt via `text` (book-to-game) — reserving one
        generation against your daily quota before spending GPU. **Import**:
        pass a compiled `world` object to persist it VERBATIM (no
        generation/GPU) — the graph is schema-validated but not recompiled, and
        it returns `201` with `imported:true`. Import still reserves one
        `generation` of quota (anti-spam) and is bounded in size (see `413`).
        Worlds created with a **live** key are attributed to your account and
        appear in your web Studio under **My Creations** (test-mode creations
        stay out of the Studio list).
      parameters:
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            type: string
          description: >
            A retried request with the same key returns the original result
            without re-generating. Keyed per (app, mode, key value) — test and
            live keep separate idempotency caches, so reusing a key across modes
            is safe.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                premise:
                  type: string
                  description: >-
                    GENERATE mode: a "what if…" pitch. Required if no frame and
                    no `world` is given.
                frame_b64:
                  type: string
                  description: 'GENERATE mode: base64 seed frame (data-URL or raw).'
                frame_url:
                  type: string
                  description: 'GENERATE mode: URL of a seed frame.'
                text:
                  type: string
                  maxLength: 40000
                  description: >
                    GENERATE mode (BOOK-TO-GAME): a chapter or book excerpt
                    turned into a playable world through the book pipeline
                    (segment → bible → author an act, fail-closed validate). One
                    chapter → one world. Mutually exclusive with
                    `premise`/`frame_b64`/`frame_url` (sending both → `400`);
                    over 40000 chars → `400`. Recommend `async:true` for
                    chapters. Meters one `generation`; tenancy, mode and author
                    stamping match every other create. `subject_ref` is NOT yet
                    supported with `text` (sending both → `400`) — to carry a
                    character across chapters, author each chapter with
                    `premise`/`frame` + `subject_ref`.
                world:
                  type: object
                  additionalProperties: true
                  description: >
                    IMPORT mode: a complete compiled SMWorld to store verbatim.
                    When present, generation is skipped and the response is 201
                    with `imported:true`. `name`/`description` (below) override
                    the blob's own.
                name:
                  type: string
                description:
                  type: string
                  description: 'IMPORT mode: overrides the imported blob''s description.'
                pov:
                  type: string
                  default: third_person_shoulder
                  description: GENERATE mode only.
                async:
                  type: boolean
                  default: false
                  description: >-
                    GENERATE mode: queue a durable job and return 202 with a
                    jobId instead of generating inline. Poll GET
                    /v1/jobs/{jobId}. (Ignored by import and by test-mode keys,
                    which return synchronously.)
                subject_ref:
                  type: object
                  description: >
                    GENERATE mode: a canonical-character reference
                    (`subjectRef`) for cross-scene consistency — the PIXEL
                    counterpart of the prose subject lock. When present, the
                    opening seed is painted FROM this character and the
                    reference is stored on the world as `subjectRef {imageUrl,
                    descriptor}`, so later scenes/levels/chapters regenerate
                    seeds that keep the same face, build, hair and clothing (see
                    `POST /v1/worlds/{id}/scenes`). A `image_b64` is hosted to a
                    durable URL first. Threads through the async job path too.
                    FAIL CLOSED: if a supplied `image_b64` cannot be hosted the
                    request returns `502` (no world is created) rather than
                    silently dropping the reference.
                  properties:
                    image_b64:
                      type: string
                      description: >-
                        Base64 reference image (raw base64; a data: URL is
                        accepted here too). Hosted to a durable URL, then
                        discarded. If hosting fails the request returns 502
                        (fail closed).
                    image_url:
                      type: string
                      description: >-
                        URL of an ALREADY-hosted reference image (used
                        verbatim). Must NOT be a data: URI — that is rejected
                        with 400 (host it first, or pass the bytes as
                        image_b64), so the two write surfaces agree and no
                        multi-MB blob is stored on the world.
                    descriptor:
                      type: string
                      description: >-
                        Optional prose descriptor of the character (defaults to
                        the world's `subject`).
      responses:
        '200':
          description: World created (generate, sync)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateWorldResponse'
        '201':
          description: World imported verbatim
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ImportWorldResponse'
        '202':
          description: Generation job queued (async)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GenerationJob'
        '400':
          description: >-
            Missing premise/frame/world; `text` sent alongside premise/frame
            (mutually exclusive) or over 40000 chars; OR an invalid subject_ref
            (a data: URI in image_url — host it first, or pass the bytes as
            image_b64).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Authentication required
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: Daily generation quota exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '413':
          description: >-
            Imported world too large (default max 2 MB / 500 states / 2000
            events).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '422':
          description: Generated/imported world failed schema validation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '502':
          description: >-
            subject_ref hosting failed — a supplied subject_ref.image_b64 could
            not be hosted to a durable URL. FAIL CLOSED: no world is created
            (the paid character reference would otherwise be silently dropped).
            Safe to retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: Quota backend unavailable (fail-closed)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - ApiKeyAuth: []
components:
  schemas:
    CreateWorldResponse:
      type: object
      properties:
        worldId:
          type: string
          format: uuid
        slug:
          type: string
          nullable: true
        ok:
          type: boolean
          description: Whether the kernel author landed clean.
        cover:
          type: string
        schemaVersion:
          type: string
          example: '1.0'
        mock:
          type: boolean
          description: >-
            Present and `true` only for TEST-mode keys — a deterministic sandbox
            response, no real generation. See Testing.
    ImportWorldResponse:
      type: object
      description: >-
        Returned by POST /v1/worlds when a compiled `world` is imported verbatim
        (201 Created).
      properties:
        worldId:
          type: string
          format: uuid
        slug:
          type: string
          nullable: true
        imported:
          type: boolean
          example: true
        schemaVersion:
          type: string
          example: '1.0'
    GenerationJob:
      type: object
      description: >
        A durable async generation job (returned by async create + GET
        /v1/jobs/{jobId}). A multi-chapter **campaign** job (`kind: from_book`,
        created by POST /v1/campaigns) reports its per-chapter progress through
        the `actsDone`/`actsTotal` counters below and carries the parent
        `campaignId`.
      properties:
        jobId:
          type: string
          format: uuid
        status:
          type: string
          enum:
            - queued
            - running
            - succeeded
            - failed
            - cancelled
        phase:
          type: string
          nullable: true
          description: >-
            Not driven for a campaign (from_book) job; use actsDone/actsTotal to
            render its progress.
        progress:
          type: number
          description: >-
            0–1 for a single-world job. NOT driven for a campaign (from_book)
            job — it stays at its queued default; use actsDone/actsTotal for a
            campaign's progress bar instead.
        worldId:
          type: string
          format: uuid
          nullable: true
          description: >-
            For a single-world job, the created world (set on success). For a
            campaign (from_book) job, the FIRST authored chapter's world id —
            read the full ordered chapter list from GET /v1/campaigns/{id}.
        campaignId:
          type: string
          format: uuid
          nullable: true
          description: >-
            The parent campaign. Populated for a multi-chapter (from_book) job;
            null on a single-world job.
        actsDone:
          type: integer
          nullable: true
          description: >-
            Chapters authored so far — advances as each chapter is authored and
            saved. Populated for a from_book campaign job; null on a
            single-world job.
        actsTotal:
          type: integer
          nullable: true
          description: >-
            Total chapters the campaign will author (the story spine's act
            count, known after the spine stage). Populated for a from_book
            campaign job; null on a single-world job.
        error:
          type: string
          nullable: true
        schemaVersion:
          type: string
          example: '1.0'
    Error:
      type: object
      properties:
        detail:
          type: string
          description: Human-readable error message.
        errors:
          type: array
          items:
            type: string
          description: Field-level validation errors (e.g. on 422 from POST /v1/worlds).
        schemaVersion:
          type: string
      required:
        - detail
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      description: >-
        An app API key, e.g. `Authorization: Bearer sk_live_…`. Secret (`sk_`)
        for writes/sessions; publishable (`pk_`) is read-only (browser-safe).

````