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

# Quickstart

> Create a website, add a page, preview it, and publish it live with the Cactal API in about five minutes.

This guide takes you from an empty organization to a website you can open in a browser, using only the REST API. The same operations are available in the [dashboard](https://app.cactal.ai), where the built-in [Cactal agent](/docs/agents/cactal-agent) can run them for you, and over [MCP](/docs/agents/mcp).

## Prerequisites

* A Cactal account — sign up at [app.cactal.ai](https://app.cactal.ai).
* An API key exported as `CACTAL_API_KEY` — see [Create an API key](/docs/create-an-api-key).

All requests go to the public API host:

```text theme={null}
https://api.cactal.ai/v1
```

<Steps>
  <Step title="Find your organization id">
    Every website belongs to an organization. List the organizations your key can access:

    ```bash List organizations theme={null}
    curl https://api.cactal.ai/v1/organizations \
      -H "Authorization: Bearer $CACTAL_API_KEY"
    ```

    The response is an array. Copy the `id` you want to create the website in:

    ```json Response theme={null}
    [
      {
        "id": "mUprfSyM4wgKY2AbQzXnE",
        "name": "Acme Studio",
        "slug": "acme-studio",
        "createdAt": "2026-07-01T15:02:11.000Z"
      }
    ]
    ```
  </Step>

  <Step title="Create a website">
    ```bash Create a website theme={null}
    curl -X POST https://api.cactal.ai/v1/websites \
      -H "Authorization: Bearer $CACTAL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "organizationId": "mUprfSyM4wgKY2AbQzXnE",
        "name": "Acme Plumbing"
      }'
    ```

    The response is the new website. `headVersion` is the draft you edit; `publishedVersion` is `null` until you publish:

    ```json Response theme={null}
    {
      "id": "V1StGXR8Z5jdHi6BmyTxQ",
      "organizationId": "mUprfSyM4wgKY2AbQzXnE",
      "name": "Acme Plumbing",
      "headVersion": 1,
      "publishedVersion": null,
      "createdAt": "2026-07-08T18:30:00.000Z",
      "updatedAt": "2026-07-08T18:30:00.000Z"
    }
    ```

    Cactal also allocates a platform subdomain for the website automatically. You'll look it up in a later step.
  </Step>

  <Step title="Acquire an edit lease">
    Source code mutations require an edit lease. Acquiring a lease returns a token; acquiring again later replaces it, so the most recent editing session always owns the draft.

    ```bash Acquire a lease theme={null}
    curl -X POST https://api.cactal.ai/v1/websiteSourceCode/lease/acquire \
      -H "Authorization: Bearer $CACTAL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "websiteId": "V1StGXR8Z5jdHi6BmyTxQ" }'
    ```

    ```json Response theme={null}
    {
      "leaseToken": "exampleLeaseToken00000000000000000000000000",
      "headVersion": 1
    }
    ```

    Learn more in [Source code](/docs/concepts/source-code).
  </Step>

  <Step title="Add a home page">
    Pages are framework source files. A page imports `definePage` from `@website`, declares its route, and renders JSX:

    ```bash Create the home page theme={null}
    curl -X PUT https://api.cactal.ai/v1/websiteSourceCode/files \
      -H "Authorization: Bearer $CACTAL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "websiteId": "V1StGXR8Z5jdHi6BmyTxQ",
        "file": { "type": "page", "name": "Home" },
        "content": "import { definePage } from '\''@website'\''\n\nexport default definePage({\n\troute: '\''/'\'',\n\trender: () => (\n\t\t<main>\n\t\t\t<h1>Acme Plumbing</h1>\n\t\t\t<p>Fast, reliable plumbing for the whole county.</p>\n\t\t</main>\n\t)\n})",
        "leaseToken": "exampleLeaseToken00000000000000000000000000"
      }'
    ```

    The page source you just uploaded, formatted for reading:

    ```tsx Home page source theme={null}
    import { definePage } from '@website'

    export default definePage({
    	route: '/',
    	render: () => (
    		<main>
    			<h1>Acme Plumbing</h1>
    			<p>Fast, reliable plumbing for the whole county.</p>
    		</main>
    	)
    })
    ```

    Every successful file write advances the website's `headVersion`.
  </Step>

  <Step title="Check the draft">
    Run the framework quality gate before publishing. It validates and type-checks your draft the same way publishing will:

    ```bash Check the draft theme={null}
    curl -X POST https://api.cactal.ai/v1/websiteSourceCode/head/check \
      -H "Authorization: Bearer $CACTAL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "websiteId": "V1StGXR8Z5jdHi6BmyTxQ" }'
    ```

    A passing check reports the draft version it validated. If the check fails, the response describes each framework error so you can fix the file and retry.
  </Step>

  <Step title="Preview the draft">
    Look up the website's platform subdomain:

    ```bash List domains theme={null}
    curl https://api.cactal.ai/v1/websites/V1StGXR8Z5jdHi6BmyTxQ/domains \
      -H "Authorization: Bearer $CACTAL_API_KEY"
    ```

    Find the domain with `"kind": "platform_subdomain"` and take its `hostname`, for example `acme-plumbing.cactal.app` or `acme-plumbing-x8k2p7.cactal.app` when a uniqueness suffix was needed. The draft preview is served at that hostname with a `draft--` prefix:

    ```text Draft preview URL theme={null}
    https://draft--acme-plumbing-x8k2p7.cactal.app
    ```

    <Check>
      Open the draft URL in a browser. You should see your Acme Plumbing home page. Draft previews always show the current head version and are never indexed by search engines.
    </Check>
  </Step>

  <Step title="Publish">
    Publishing builds the draft in an isolated sandbox and, on success, makes it the live version:

    ```bash Publish the draft theme={null}
    curl -X POST https://api.cactal.ai/v1/websiteSourceCode/head/publish \
      -H "Authorization: Bearer $CACTAL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "websiteId": "V1StGXR8Z5jdHi6BmyTxQ",
        "leaseToken": "exampleLeaseToken00000000000000000000000000"
      }'
    ```

    <Note>
      A site counts toward your plan when an organization owner enables custom domains for it. Sites on Cactal domains are unlimited and free. See [Plans and limits](/docs/platform/plans-and-limits).
    </Note>

    <Check>
      Open `https://acme-plumbing-x8k2.cactal.app` (no `draft--` prefix). Your website is live.
    </Check>
  </Step>
</Steps>

## What you built

You created a website, edited its draft under a lease, validated it, previewed it, and published it. The draft/publish split is the core of Cactal: nothing goes live until you publish, and every published version can be [rolled back](/docs/guides/roll-back-and-recover).

## Next steps

<Columns cols={2}>
  <Card title="Manage content with the CMS" icon="database" href="/docs/guides/manage-cms-content">
    Model collections and fields, then publish structured content.
  </Card>

  <Card title="Connect a custom domain" icon="link" href="/docs/guides/connect-a-custom-domain">
    Point your own domain at the website and make it primary.
  </Card>

  <Card title="Connect your agent" icon="bot" href="/docs/agents/mcp">
    Run this whole flow through MCP from Claude, Cursor, or any MCP client.
  </Card>

  <Card title="Edit source code" icon="file-code" href="/docs/guides/edit-source-code">
    Components, global CSS, page metadata, and custom code slots.
  </Card>

  <Card title="Build pages with CMS data" icon="blocks" href="/docs/guides/build-pages-with-cms-data">
    Query published content through the generated website SDK.
  </Card>

  <Card title="Configure routes and redirects" icon="route" href="/docs/guides/configure-routes-and-redirects">
    Define page URLs and safe migrations.
  </Card>

  <Card title="Style a website" icon="palette" href="/docs/guides/style-a-website">
    Add global CSS, Tailwind utilities, and theme tokens.
  </Card>

  <Card title="Configure SEO metadata" icon="search" href="/docs/guides/configure-seo-metadata">
    Build titles, social previews, and structured data from CMS content.
  </Card>
</Columns>
