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

# REST API

> Create, generate, edit and publish sites from your own code. Agency plan.

The API at `https://api.getsite.ai/v1` is the same one the app uses. API access is part of the Agency plan.

## Get a key

Go to [app.getsite.ai/account/api-keys](https://app.getsite.ai/account/api-keys), name the key and click **Generate key**. Copy it right away; it is shown once. Keys look like `gsk_` followed by 64 hex characters.

Up to 10 active keys. **Revoke** is immediate and permanent. Keys stop working while your plan has no API access and start working again when it does.

## Authenticate

```bash theme={null}
curl https://api.getsite.ai/v1/users/me \
  -H "Authorization: Bearer gsk_..."
```

A missing or bad key returns `401` with a plain-text `Unauthorized` body, not JSON. Call the API from a server, a CLI or an agent. Browsers on other origins are blocked.

## Reference

The interactive reference is a Swagger UI at [api.getsite.ai/docs](https://api.getsite.ai/docs). It is behind a login; the credentials are on the API Keys page under **Show Credentials**. The same page has **Generate Skill**, a prompt that teaches an AI coding agent to use the API with your key.

## Build and publish a site

Generation is asynchronous: start a run, poll it, then publish.

<Steps>
  <Step title="Create the website">
    ```bash theme={null}
    curl -X POST https://api.getsite.ai/v1/websites \
      -H "Authorization: Bearer gsk_..." \
      -H "Content-Type: application/json" \
      -d '{"prompt": "Landing page for a dog grooming studio in Austin", "name": "Pawfect"}'
    ```

    Returns the website with its `_id`. No AI runs yet.
  </Step>

  <Step title="Create the home page">
    ```bash theme={null}
    curl -X POST https://api.getsite.ai/v1/websites/WEBSITE_ID/pages \
      -H "Authorization: Bearer gsk_..." \
      -H "Content-Type: application/json" \
      -d '{"path": "/", "name": "Home", "prompt": "Landing page for a dog grooming studio in Austin. Hero, services, prices, testimonials, contact form."}'
    ```

    If `prompt` is omitted the page inherits the website prompt.
  </Step>

  <Step title="Generate it">
    ```bash theme={null}
    curl -X POST https://api.getsite.ai/v1/pages/PAGE_ID/generate \
      -H "Authorization: Bearer gsk_..." \
      -H "Content-Type: application/json" \
      -d '{"generate_images": true, "model": "claude-opus-5-5"}'
    ```

    Returns `{"page_id": "...", "run_id": "..."}`. Credits are checked first: 20 for the page (40 with `claude-fable-5-1`), plus 10 with `generate_images`. The API never pauses a run to ask questions.
  </Step>

  <Step title="Poll the run">
    ```bash theme={null}
    curl https://api.getsite.ai/v1/runs/RUN_ID \
      -H "Authorization: Bearer gsk_..."
    ```

    Poll every few seconds until `status` is `completed`, `failed` or `stopped`. `GET /v1/runs/RUN_ID/events` streams the same progress as Server-Sent Events. The result is the page's draft version. `POST /v1/runs/RUN_ID/stop` cancels for free until code generation starts; after that it returns `409 too_late`.
  </Step>

  <Step title="Publish">
    ```bash theme={null}
    curl -X POST https://api.getsite.ai/v1/tools/deploy \
      -H "Authorization: Bearer gsk_..." \
      -H "Content-Type: application/json" \
      -d '{"page_id": "PAGE_ID", "subdomain": "pawfect", "domain": "getsite.co"}'
    ```

    `domain` is `getsite.co` (default) or `getsite.online`. `subdomain` and `domain` only count on the first publish: once the site has an address, every later deploy of any of its pages goes there and both fields are ignored. For a custom domain, add it with `POST /v1/domains`, link it with `PUT /v1/websites/WEBSITE_ID {"domain": "DOMAIN_ID"}` (this re-points every page of the site), then deploy without `subdomain`. Publishing requires an active paid plan.
  </Step>
</Steps>

Add more pages by repeating steps 2 to 4 with another path. The home page must be generated first; other pages return `409 homepage_not_generated` until then. `POST /v1/tools/suggest_pages {"prompt": "..."}` proposes a sitemap for free.

To write a page without AI: `POST /v1/websites/WEBSITE_ID/pages/import {"path", "name", "html", "css", "javascript"}` creates a page from your code (not for `/`). To replace the code of an existing page, including the home page, save a version: `POST /v1/versions {"page_id", "thread_id", "html", "css", "javascript"?}`, where `thread_id` is a thread on that page from `POST /v1/threads`. Then deploy.

### Models

`model` is accepted by `POST /v1/pages/:id/generate` and `POST /v1/edit/turn`.

| Id | Credits | |
| - | - | - |
| `claude-opus-5-5` | 1x | Default |
| `claude-fable-5-1` | 2x | Paid plans |

Unknown ids return `400`. A model your plan does not allow silently falls back to the default and is billed at the default rate.

## Edit a page with AI

`POST /v1/edit/turn {"page_id", "message", "thread_id"?, "model"?, "attachments"?}` runs one turn of the editor chat and streams the result as Server-Sent Events. The first event, `turn_start`, carries the `thread_id`; pass it on the next call to continue the conversation, otherwise every call starts a new thread with no history. One turn per thread at a time (`409 turn_in_progress`). Messages up to 10,000 characters, up to 4 image URLs. Costs 10 credits plus 10 per 50 KB of page code, times the model multiplier. A reply that changes nothing is free.

## Endpoints

| Group | Endpoints |
| - | - |
| Websites | `GET POST /v1/websites`, `GET PUT DELETE /v1/websites/:id`, `GET POST /v1/websites/:id/pages`, `POST /v1/websites/:id/pages/import`, `POST /v1/websites/:id/duplicate`, `GET /v1/websites/:id/analytics` |
| Pages | `GET /v1/pages`, `GET PUT DELETE /v1/pages/:id`, `POST /v1/pages/:id/generate`, `POST /v1/pages/:id/clone`, `GET /v1/pages/:id/versions`, `GET /v1/pages/:id/analytics` |
| Runs | `GET /v1/runs`, `GET /v1/runs/:id`, `GET /v1/runs/:id/events`, `POST /v1/runs/:id/stop` |
| Versions | `GET /v1/versions/:id`, `POST /v1/versions`, `POST /v1/versions/:id/restore` |
| Publish | `POST /v1/tools/deploy` |
| Edit chat | `POST /v1/edit/turn` |
| AI tools | `POST /v1/tools/suggest_pages`, `generate_image`, `generate_logo`, `generate_og_image`, `generate_design`, `generate_email`, `generate_metadata`, `generate_domains`, `generate_subdomain`, `check_domain`, `regenerate_section`, `regenerate_text` |
| Forms | `GET /v1/forms`, `GET PUT DELETE /v1/forms/:id`, `GET /v1/forms/:id/submissions`, `GET /v1/forms/emails`, `GET /v1/submissions`, `DELETE /v1/submissions/:id` |
| Domains | `GET POST /v1/domains`, `GET PUT DELETE /v1/domains/:id`, `POST /v1/domains/:id/dns`, `DELETE /v1/domains/:id/dns/:record_id`, `POST /v1/domains/:id/subdomain`, `GET /v1/domains/:id/uptime`, `GET /v1/domains/:id/analytics` |
| Leads | `POST /v1/leads/search`, `GET /v1/leads`, `GET PUT DELETE /v1/leads/:id`, `POST /v1/leads/:id/enrich`, `GET /v1/leads/searches`, `GET /v1/leads/stats`, `GET /v1/leads/export` |
| CMS | `GET POST /v1/websites/:id/cms/collections`, `PUT DELETE /v1/cms/collections/:id`, `GET POST /v1/cms/collections/:id/records`, `PUT DELETE /v1/cms/records/:id` |
| Account | `GET /v1/users/me`, `GET /v1/users/me/stats`, `GET /v1/credits`, `GET /v1/subscriptions`, `GET /v1/payments`, `GET POST /v1/api_keys`, `DELETE /v1/api_keys/:id` |

Campaigns and experiments endpoints are in the Swagger reference; CMS endpoints are not yet. Plan gates and credit costs are the same as in the app. Registering a domain starts with `POST /v1/domains {"domain", "mode": "register", "purchase_years"}` and `POST /v1/lemonsqueezy/checkout {"domain_id"}`, which returns a checkout URL to open in a browser.

Deleting a website deletes its pages and unlinks its domains. Deleting a site's last page deletes the website.

## Pagination

List endpoints take `limit` and `page`. `page` starts at 0, except the Leads endpoints, where it starts at 1.

## Errors

Errors are JSON: `{"error": true, "message": "..."}`.

| Status | Meaning |
| - | - |
| `400` | Validation failed. `details` lists the issues on most routes |
| `401` | Missing or invalid key. Plain-text `Unauthorized` body |
| `402` | Not enough credits. `available` is included, with `required` (generate) or `needed` (edit) |
| `403` | Not on your plan (`feature`, `required_plan`) |
| `409` | Conflict: page already generating, home page not generated, duplicate path, run too late to stop |
| `429` | Rate limit. Try again after 15 minutes |

`POST /v1/tools/deploy` and `POST /v1/versions` answer bad input with a `500` and a `message`.

## Rate limits

Per route, per account (all your keys share one bucket), in 15-minute windows. Default 100 requests. Create and publish writes are lower: `POST /v1/websites`, `POST /v1/websites/:id/pages`, `POST /v1/websites/:id/pages/import` and `POST /v1/pages/:id/generate` 30, `POST /v1/tools/deploy` 50, `POST /v1/edit/turn` 200. Most list and detail reads are higher (1,000 to 5,000); analytics reads and `GET /v1/leads/export` stay at 50 to 500. Request bodies are limited to 5 MB.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.