On this page

Home / Documentation / API reference

API reference

HTTP surface for sites, pages, blocks, media, CMS, and billing—aligned with the dashboard. Use the sidebar to jump within this page. New to SlateHut? Read the documentation hub first, then come back here for routes, schemas, and examples.

Introduction

Base paths are under /api/v1. Authenticated routes accept a Bearer API key or, on this origin, a signed-in session. The sections below document authentication, limits, and the embedded OpenAPI narrative; then the full route list, generated from the same spec we ship as JSON.

Conceptual overview, workspace behavior, and capability summaries live on the main documentation page.

Authentication

Create a secret key under API keys in the dashboard. Send Authorization: Bearer sh_live_… on each call. Signed-in visitors can also call these routes from the browser without a header. See Examples → Auth header.

Base URL and limits

Base URL

All versioned routes hang off your SlateHut host.

https://slatehut.com/api/v1

Rate limits

Up to 60 requests per minute for each API key or session. Expect 429 when you exceed that window.

OpenAPI specification

We ship OpenAPI 3.1 JSON so you can import into Postman, generate typed clients, or diff changes between releases. The prose below is mirrored from the spec itself.

SlateHut APIv1.0.0120 schemas

Server URL in the document
https://slatehut.com

Auth style: HTTP bearer — API key from Dashboard → API Keys (prefix `sh_live_`)

Use this API from your own scripts and integrations to create and update SlateHut sites—pages, themes, forms, media, and more—so they stay aligned with what you see in the dashboard.

Workspaces: API keys and browser sessions are scoped to an active workspace. Bearer keys belong to one workspace; GET /api/v1/sites lists sites in that workspace only. The dashboard lets you switch workspaces (each has its own plan and AI credit pool).

Authenticate with Authorization: Bearer <api_key> (keys start with sh_live_; create keys in the dashboard on any plan). If you are logged into SlateHut in the browser, your session also works for the same endpoints on this website. Rate limit: 60 requests per minute per API key or session.

Same behavior as the dashboard: Site document GET/PUT, CMS, domains, preview token, per-site form submissions, file upload, Unsplash search/import (requires UNSPLASH_ACCESS_KEY on our servers), subdomain availability, and sync-chrome (navbar/footer sync across pages) match what you can do in the product.

Granular pages & blocks: GET/POST /api/v1/sites/{subdomain}/pages, GET/PUT/DELETE …/pages/{pagePath}, and block CRUD under …/pages/{pagePath}/blocks (plus PATCH …/blocks/reorder) update the same JSON document as the editor. Path segment pagePath: use _ for the home page; nested slugs use one encoded segment (e.g. legal%2Fprivacy). Query scope=template targets dynamic.templateBlocks on CMS pages. Every PageBlock may include optional animation (BlockAnimation: preset, scroll|load trigger, timing) plus animatedHero, logoCloud, featureShowcase, metricsBand, comparisonTable, faqAccordion, and gallery3d block types alongside the existing library.

Images: POST /api/v1/media/upload (multipart file), or Unsplash GET …/media/unsplash/search (supports orientation and color filters) + POST …/media/unsplash/import with { photoId }{ url, alt, attribution }. You must display attribution.html (or an equivalent link credit) wherever the imported image appears — this is required by the Unsplash API license.

Built-in templates: GET /api/v1/templates lists curated ids (aiSaas, financialAdvisor, lawFirm, medicalAesthetic, realEstate, executiveCoach, agency, boutiqueHotel, weddingVenue, interiorDesign, dtcProduct, onlineCourse, fineDining, luxuryPortfolio, comingSoon) with premium home layouts; pass templateId on create or generation to start from one.

AI site generation: POST /api/v1/sites/generate runs plan + home page in one call (gated by workspace AI credits in USD, not a monthly run count). For human review, use POST /api/v1/sites/generate/plan (returns JSON plan) then POST /api/v1/sites/generate/from-plan with that plan—same persistence as POST /api/v1/sites. Single home page only (/). Optional Unsplash images.

Billing (Stripe): POST /api/v1/billing/checkout returns an embedded Checkout clientSecret for a workspace subscription (owner/admin only). POST /api/v1/billing/portal returns a Stripe Customer Portal URL. GET /api/v1/billing/status returns the active workspace billing summary. Plan changes sync from Stripe webhooks to the workspace billingPlan.

Pages: pages[] = SitePageDef; each blocks[] entry = PageBlock (discriminated type + *BlockProps), including optional custom blocks (sanitized HTML + Tailwind + scoped css with .ai-custom-root selectors). Set optional anchorId on any block to give it an HTML id for in-page anchors (e.g. navbar link #pricing scrolls to the block with anchorId: "pricing"). When creating CMS collections with attachDynamicPage, the home page navbar and footer are automatically copied to the new dynamic page. Use POST …/collections/{collectionId}/attach-dynamic-page to attach a minimal list/detail page to an existing collection. CMS detail metadata uses dynamic.seoMapping: field ids plus optional *Template strings with {{fieldId}} placeholders filled from entry data (see CmsSeoMapping).

MCP (Model Context Protocol): POST, GET, and DELETE on /api/mcp expose Streamable HTTP for AI clients (Cursor, ChatGPT, Claude, and others). Authenticate with Authorization: Bearer <api_key> (sh_live_…, same as REST v1) or complete OAuth 2.1 via /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server (token endpoints under /api/oauth). MCP tools mirror site creation (create_site, create_site_from_template), deletion (delete_site with confirm: true), templates, pages, theme, subdomain checks, media (Unsplash with orientation/color filters + attribution), CMS, domains, and form submissions; prompts provide canned site-type briefs. Agents can discover block shapes through MCP resources — schema://blocks (index), schema://blocks/{type} (full JSON schema: shell + props + resolved component refs), schema://theme, example://blocks/{type}, example://sites/{templateId}, site://{subdomain}, site://{subdomain}/pages/{pageSlug} — and block/page/site mutations return field-path validation errors (e.g. props.variant: Invalid enum value) so they can self-correct. Requires MCPAUTH_SECRET (HMAC for signed authorize state) and MCPAUTH_PRIVATE_KEY (RSA PEM for JWKS) when using the OAuth flow.

Editor-only: Live preview hydration actions (no public HTTP surface).

Download the live file: https://slatehut.com/api/v1/openapi.json

Grab it with curl if you want a local copy in one command.

Model Context Protocol (MCP)

Connect Cursor, ChatGPT, Claude, and other MCP clients to /api/mcp (Streamable HTTP). Use the same sh_live_ API key as REST v1, or run the OAuth 2.1 flow discovered from /.well-known/oauth-protected-resource (authorization server metadata at /.well-known/oauth-authorization-server; token endpoints under /api/oauth). Sign in on the web when the authorize step redirects to login. OAuth issuance requires MCPAUTH_SECRET and MCPAUTH_PRIVATE_KEY (RSA PEM) in the server environment.

MCP installation snippets and product-oriented guide →

Tools

  • create_site — AI generation from a prompt
  • create_site_from_template — non-AI template site
  • list_sites, get_site, update_site_theme
  • add_page, update_page, delete_page
  • list_templates, check_subdomain

Prompts

Canned briefs align with built-in templates (AI SaaS, wealth, law, med spa, real estate, coaching, agency, hospitality, events, interiors, DTC, courses, dining, portfolio, coming soon).

OpenAPI lists MCP-related paths under the mcp tag.

Build a site with this API (for agents)

Follow the steps in order. Each step names the HTTP method and path; the Examples section below has working payloads in curl, JavaScript, and Python.

  1. Create or pick a site. POST /api/v1/sites with a template, or POST /api/v1/sites/generate when you want AI to draft the first home page. Optional: GET /api/v1/sites/availability?q=… before you commit a subdomain.
  2. Inspect pages. GET /api/v1/sites/{subdomain}/pages lists routes; GET …/pages/_ returns the home document with blocks.
  3. Shape the layout. Add blocks with POST …/blocks, update with PUT …/blocks/{id}, or reorder via PATCH …/blocks/reorder. Use the Data models section for props per block type.
  4. Add assets. POST /api/v1/media/upload accepts multipart files; reference the returned URL inside hero, gallery, or rich blocks.
  5. Tune the theme. PUT /api/v1/sites/{subdomain} with a theme object merges into the existing palette.
  6. Verify in the browser. Open the public URL for that subdomain on your SlateHut host (or the custom domain after DNS verifies) and confirm the live page matches the JSON you saved.

Need raw HTTP samples? Jump to the Examples.

All endpoints

Every row matches the published OpenAPI document. Path-level parameters apply to every method on that URL. Bearer means an API key or session cookie; Public means no authentication.

templatesBuilt-in site templates (no auth)

get/api/v1/openapi.jsonPublic

OpenAPI document

Responses

  • 200This OpenAPI JSON
get/api/v1/templatesPublic

List site templates

Responses

  • 200Template metadata

cmsCMS presets (no auth)

get/api/v1/cms/presetsPublic

List CMS collection presets (blog, directory)

Responses

  • 200Preset ids and descriptions

sitesSite CRUD (auth required)

get/api/v1/sitesBearer

List current workspace's sites

Responses

  • 200Site list (SiteListResponse)
  • 401Missing or invalid credentials
post/api/v1/sitesBearer

Create a site

Request body

application/json · CreateSiteRequest

Responses

  • 201Created
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 409Validation or conflict error
  • 503Validation or conflict error
post/api/v1/sites/generateBearer

Create a site from an AI prompt

Runs structured LLM calls (Vercel AI Gateway): a site plan (Sonnet) then one call for the single home page blocks (Sonnet; native typed blocks such as hero, features, cta, pricing, plus form/rich/etc.), then persists like POST /api/v1/sites. For a two-step flow with plan review, use POST /api/v1/sites/generate/plan then POST /api/v1/sites/generate/from-plan. Image URLs: Unsplash + Blob when configured; otherwise Picsum placeholders.

Request body

application/json · required · GenerateSiteRequest

Responses

  • 201Created
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 409Validation or conflict error
  • 502Validation or conflict error
  • 503Validation or conflict error
post/api/v1/sites/generate/planBearer

Create a site plan from a prompt (AI)

Returns JSON plan (theme, navbar, footer, single home page purpose)—same shape required by POST /api/v1/sites/generate/from-plan. Non-streaming; mirrors a plan-only step for programmatic flows; the dashboard New site page (/dashboard/new) uses one-step streaming generation instead.

Request body

application/json · required · GenerateSitePlanRequest

Responses

  • 200Site plan JSON
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 502Validation or conflict error
post/api/v1/sites/generate/from-planBearer

Create a site from an approved AI plan

Generates home page blocks from a plan returned by POST /api/v1/sites/generate/plan (optionally edited), then persists like POST /api/v1/sites/generate.

Request body

application/json · required · GenerateSiteFromPlanRequest

Responses

  • 201Created
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 409Validation or conflict error
  • 502Validation or conflict error
  • 503Validation or conflict error
get/api/v1/sites/availabilityBearer

Check if a subdomain is valid and available

Same rules as the editor: normalization, reserved names, length 2–48, uniqueness. Empty q returns { normalized: "", available: true }.

Parameters

NameInReqDetails
qquerynostringProposed subdomain string

Responses

  • 200normalized slug and whether it can be registered (SubdomainAvailabilityResponse)
  • 400Validation or conflict error
  • 401Missing or invalid credentials
get/api/v1/sites/{subdomain}Bearer

Get site document

Parameters

NameInReqDetails
subdomainpathyesstring
includequerynostringComma-separated projection: pages, theme, chrome, title, description, meta, or all (default full document).

Responses

  • 200Site payload (SiteGetResponse)
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
put/api/v1/sites/{subdomain}Bearer

Update site

Parameters

NameInReqDetails
subdomainpathyesstring

Request body

application/json · required · UpdateSiteRequest

Responses

  • 200Updated
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
  • 409Validation or conflict error
delete/api/v1/sites/{subdomain}Bearer

Delete site

Permanently deletes the site and its data. Any custom domains attached to the site are removed from the hosting project on Vercel before the database row is deleted (same as removing each domain via DELETE …/domains/{hostname}).

Parameters

NameInReqDetails
subdomainpathyesstring

Responses

  • 200Deleted
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
get/api/v1/sites/{subdomain}/pagesBearer

List pages (slug, path, block counts)

Returns a lightweight summary per page. Full SitePageDef is available via GET …/pages/{pagePath}.

Parameters

NameInReqDetails
subdomainpathyesstring

Responses

  • 200Page summaries (SitePageListResponse)
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
post/api/v1/sites/{subdomain}/pagesBearer

Create a new page

Adds a route under the site. slug must not be empty (use _ in pagePath only when addressing the existing home page on other routes). Defaults to a single text block if blocks is omitted.

Parameters

NameInReqDetails
subdomainpathyesstring

Request body

application/json · required · CreateSitePageRequest

Responses

  • 201Created page
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
  • 409Validation or conflict error
get/api/v1/sites/{subdomain}/pages/{pagePath}Bearer

Get one page (full SitePageDef)

Parameters

NameInReqDetails
subdomainpathyesstring
pagePathpathyesstringSingle URL segment for the page slug. Use `_` for home (`slug === ""`). Nested slugs: encode slashes, e.g. `legal%2Fprivacy`.

Responses

  • 200200
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
put/api/v1/sites/{subdomain}/pages/{pagePath}Bearer

Update one page

Partial update: omit fields to keep current values. Set dynamic to null to remove CMS wiring. seo can be set to null to clear.

Parameters

NameInReqDetails
subdomainpathyesstring
pagePathpathyesstringSingle URL segment for the page slug. Use `_` for home (`slug === ""`). Nested slugs: encode slashes, e.g. `legal%2Fprivacy`.

Request body

application/json · required · UpdateSitePageRequest

Responses

  • 200200
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
delete/api/v1/sites/{subdomain}/pages/{pagePath}Bearer

Delete a page

Cannot delete the home page or the only remaining page.

Parameters

NameInReqDetails
subdomainpathyesstring
pagePathpathyesstringSingle URL segment for the page slug. Use `_` for home (`slug === ""`). Nested slugs: encode slashes, e.g. `legal%2Fprivacy`.

Responses

  • 200200
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
get/api/v1/sites/{subdomain}/pages/{pagePath}/blocksBearer

List blocks on a page

Parameters

NameInReqDetails
subdomainpathyesstring
pagePathpathyesstringSame as single-page GET: `_` = home; nested = encodeURIComponent.
scopequerynoindex | template`index` (default) = page `blocks`. `template` = `dynamic.templateBlocks` on CMS pages.

Responses

  • 200200 (PageBlockListResponse)
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
post/api/v1/sites/{subdomain}/pages/{pagePath}/blocksBearer

Add a block

Optional position (0-based insert index; default append).

Parameters

NameInReqDetails
subdomainpathyesstring
pagePathpathyesstringSame as single-page GET: `_` = home; nested = encodeURIComponent.
scopequerynoindex | template`index` (default) = page `blocks`. `template` = `dynamic.templateBlocks` on CMS pages.

Request body

application/json · required · AddSiteBlockRequest

Responses

  • 201201
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
patch/api/v1/sites/{subdomain}/pages/{pagePath}/blocks/reorderBearer

Reorder blocks

blockIds must list every block id exactly once.

Parameters

NameInReqDetails
subdomainpathyesstring
pagePathpathyesstring
scopequerynoindex | template

Request body

application/json · required · ReorderBlocksRequest

Responses

  • 200200
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
get/api/v1/sites/{subdomain}/pages/{pagePath}/blocks/{blockId}Bearer

Get one block

Parameters

NameInReqDetails
subdomainpathyesstring
pagePathpathyesstring
blockIdpathyesstring
scopequerynoindex | template

Responses

  • 200200
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
put/api/v1/sites/{subdomain}/pages/{pagePath}/blocks/{blockId}Bearer

Patch block shell / props

Shallow-merge props onto existing props. anchorId / colorOverrides null clears. type and id cannot be changed.

Parameters

NameInReqDetails
subdomainpathyesstring
pagePathpathyesstring
blockIdpathyesstring
scopequerynoindex | template

Request body

application/json · required · BlockPatchRequest

Responses

  • 200200
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
delete/api/v1/sites/{subdomain}/pages/{pagePath}/blocks/{blockId}Bearer

Remove a block

Cannot remove the last block on a page or template.

Parameters

NameInReqDetails
subdomainpathyesstring
pagePathpathyesstring
blockIdpathyesstring
scopequerynoindex | template

Responses

  • 200200
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
post/api/v1/sites/{subdomain}/sync-chromeBearer

Sync navbar & footer from one page to all pages

Copies the navbar and footer blocks from a source page (default: home) to every other page on the site, including dynamic.templateBlocks for CMS detail pages. Mirrors the editor's "Apply to all pages" action. Existing navbar/footer blocks on target pages are replaced in-place; pages without them get the block prepended (navbar) or appended (footer).

Parameters

NameInReqDetails
subdomainpathyesstring

Request body

application/json

Responses

  • 200Sync complete
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
post/api/v1/sites/{subdomain}/preview-tokenBearer

Regenerate draft preview token

Parameters

NameInReqDetails
subdomainpathyesstring

Responses

  • 200previewToken

collectionsCMS collections per site (auth)

get/api/v1/sites/{subdomain}/collectionsBearer

List CMS collections

Parameters

NameInReqDetails
subdomainpathyesstring

Responses

  • 200All collections for the site (CmsCollectionsListResponse)
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
post/api/v1/sites/{subdomain}/collectionsBearer

Create collection (preset: blog|directory, or manual fields). Manual `fields` must include the `slugField` id as a text field with `required: true`. Optional attachDynamicPage adds a dynamic list/detail route with the home page navbar/footer auto-copied.

Parameters

NameInReqDetails
subdomainpathyesstring

Request body

application/json · CreateCollectionRequest

Responses

  • 201Collection created
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 409Validation or conflict error
get/api/v1/sites/{subdomain}/collections/{collectionId}Bearer

Get collection schema

Parameters

NameInReqDetails
subdomainpathyesstring
collectionIdpathyesstring

Responses

  • 200200
  • 404Resource not found
patch/api/v1/sites/{subdomain}/collections/{collectionId}Bearer

Update collection schema (fields and title/slug/content/image pointers)

Cannot change the type of an existing field id; remove and add a new field instead. The field whose id matches slugField must remain present, have type text, and required: true.

Parameters

NameInReqDetails
subdomainpathyesstring
collectionIdpathyesstring

Request body

application/json · required

Responses

  • 200200
  • 400Validation or conflict error
  • 404Resource not found
delete/api/v1/sites/{subdomain}/collections/{collectionId}Bearer

Delete collection and its items

Parameters

NameInReqDetails
subdomainpathyesstring
collectionIdpathyesstring

Responses

  • 200200
  • 404Resource not found
post/api/v1/sites/{subdomain}/collections/{collectionId}/attach-dynamic-pageBearer

Attach minimal CMS list + detail page to an existing collection (copies home navbar/footer)

Parameters

NameInReqDetails
subdomainpathyesstring
collectionIdpathyesstring

Request body

application/json · required · AttachDynamicPageRequest

Responses

  • 200200
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
get/api/v1/sites/{subdomain}/collections/{collectionId}/itemsBearer

List items (query: page, limit, status=draft|published|all, sortField, sortOrder)

Parameters

NameInReqDetails
subdomainpathyesstring
collectionIdpathyesstring

Responses

  • 200200 (CmsItemsListResponse)
post/api/v1/sites/{subdomain}/collections/{collectionId}/itemsBearer

Create CMS item

Parameters

NameInReqDetails
subdomainpathyesstring
collectionIdpathyesstring

Request body

application/json · required · CmsItemWriteRequest

Responses

  • 201201
  • 409Validation or conflict error
get/api/v1/sites/{subdomain}/collections/{collectionId}/items/{itemId}Bearer

Get item

Parameters

NameInReqDetails
subdomainpathyesstring
collectionIdpathyesstring
itemIdpathyesstring

Responses

  • 200200
  • 404Resource not found
put/api/v1/sites/{subdomain}/collections/{collectionId}/items/{itemId}Bearer

Update item

Parameters

NameInReqDetails
subdomainpathyesstring
collectionIdpathyesstring
itemIdpathyesstring

Request body

application/json · required · CmsItemWriteRequest

Responses

  • 200200
delete/api/v1/sites/{subdomain}/collections/{collectionId}/items/{itemId}Bearer

Delete item

Parameters

NameInReqDetails
subdomainpathyesstring
collectionIdpathyesstring
itemIdpathyesstring

Responses

  • 200success

domainsCustom hostnames (auth, Vercel configured)

get/api/v1/sites/{subdomain}/domainsBearer

List custom domains; ?status=1 includes Vercel DNS status per host

Parameters

NameInReqDetails
subdomainpathyesstring

Responses

  • 200domains[], optional statusByDomain
post/api/v1/sites/{subdomain}/domainsBearer

Add custom domain (Vercel project must be configured)

Registers exactly the given hostname on the Vercel project (e.g. example.com or www.example.com). Add each variant separately if you need both.

Parameters

NameInReqDetails
subdomainpathyesstring

Request body

application/json · required

Responses

  • 201domain
  • 409Validation or conflict error
delete/api/v1/sites/{subdomain}/domains/{hostname}Bearer

Remove custom domain

Parameters

NameInReqDetails
subdomainpathyesstring
hostnamepathyesstringURL-encoded hostname (e.g. encodeURIComponent)

Responses

  • 200success
post/api/v1/sites/{subdomain}/domains/{hostname}/verifyBearer

Trigger Vercel domain verification

Parameters

NameInReqDetails
subdomainpathyesstring
hostnamepathyesstring

Responses

  • 200success

mediaUpload images/files for use in block props (auth)

post/api/v1/media/uploadBearer

Upload file (multipart) — returns public URL for block props

Multipart form field file. Max size matches dashboard uploads (4 MB). Use the url in hero, gallery, navbar, imageText, etc.

Request body

multipart/form-data · required

Responses

  • 200Public blob URL
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 503Validation or conflict error

submissionsForm and newsletter signup responses from published sites (auth). The product shows each site’s inbox under that site; `GET /api/v1/submissions` lists across the active workspace’s sites for integrations. Visitor `POST /api/forms/submit` and `POST /api/newsletter/submit` count toward the workspace plan’s monthly submission cap and return **403** when the cap is reached (Free plan).

get/api/v1/submissionsBearer

List form submissions across all sites you own

Cross-site list for scripts and integrations (the dashboard uses per-site GET /api/v1/sites/{subdomain}/submissions). Use query subdomain to limit to one site. Pass cursor = previous response nextCursor (a submittedAt timestamp) for the next page.

Parameters

NameInReqDetails
subdomainquerynostringOptional; restrict to this site subdomain
cursorquerynostringPagination: prior `nextCursor` (numeric submittedAt)

Responses

  • 200Submissions include `siteTitle` for cross-site display (AccountSubmissionsResponse)
  • 401Missing or invalid credentials
get/api/v1/sites/{subdomain}/submissionsBearer

List form and newsletter submissions for one site

Parameters

NameInReqDetails
subdomainpathyesstring
formBlockIdquerynostringOptional; filter to one block id from site JSON (`form` or `newsletter` block)
cursorquerynostringPagination: prior `nextCursor`

Responses

  • 200200 (SiteSubmissionsResponse)
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
get/api/v1/sites/{subdomain}/submissions/countsBearer

Submission counts per form or newsletter block (editor sidebar)

Parameters

NameInReqDetails
subdomainpathyesstring

Responses

  • 200200 (SubmissionCountsResponse)
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found
delete/api/v1/sites/{subdomain}/submissions/{submissionId}Bearer

Delete one submission

Parameters

NameInReqDetails
subdomainpathyesstring
submissionIdpathyesstring

Responses

  • 200200
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 404Resource not found

unsplashStock photo search and import via Unsplash API (requires UNSPLASH_ACCESS_KEY on server)

post/api/v1/media/unsplash/importBearer

Import Unsplash photo to Blob storage

Triggers the Unsplash download-tracking endpoint, stores an optimized copy on your Blob, and returns { url, alt, attribution }. Per the Unsplash API license you MUST display attribution.html (or an equivalent link credit) wherever the imported image is shown. Body: { "photoId": "<id from search>" }.

Request body

application/json · required

Responses

  • 200200
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 413Validation or conflict error
  • 502Validation or conflict error
  • 503Validation or conflict error

billingStripe subscription checkout (embedded), Customer Portal, and billing status for the active workspace (owner/admin only for checkout and portal)

post/api/v1/billing/checkoutBearer

Create embedded subscription checkout session

Returns clientSecret for Stripe Embedded Checkout (@stripe/stripe-js initEmbeddedCheckout). Requires six recurring price env vars on the server (STRIPE_PRICE_*). Owner or admin only.

Request body

application/json · required · BillingCheckoutRequest

Responses

  • 200Checkout client secret (BillingCheckoutResponse)
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 409Validation or conflict error
  • 503Validation or conflict error
post/api/v1/billing/portalBearer

Create Stripe Customer Portal session

Responses

  • 200Redirect URL for the portal (BillingPortalResponse)
  • 400Validation or conflict error
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 500Validation or conflict error
get/api/v1/billing/statusBearer

Billing status for the active workspace

Responses

  • 200Effective plan and Stripe subscription fields (BillingStatusResponse)
  • 401Missing or invalid credentials
  • 403Not allowed for this resource
  • 500Validation or conflict error

mcpModel Context Protocol (Streamable HTTP) for AI assistants; OAuth discovery at /.well-known/* and token routes under /api/oauth. Tools: create_site (AI credits; optional includeCms), create_site_from_template, list_sites, get_site (optional ?include= on REST mirror), update_site, update_site_theme, edit_site (AI credits), add_page, update_page, delete_page, list_page_blocks, get_block, add_block, update_block, delete_block, reorder_blocks, upload_image, unsplash_search, unsplash_import, list_collections, get_collection, create_collection, update_collection, delete_collection, list_items, get_item, create_item, update_item, delete_item, attach_dynamic_page, list_domains, add_domain, remove_domain, check_domain_verification, verify_domain, list_form_submissions, list_newsletter_submissions, list_templates, check_subdomain. Resources: site://{subdomain}, site://{subdomain}/pages/{pageSlug}, schema://blocks, schema://blocks/{type}, schema://theme. Structured JSON is returned as structuredContent where supported.

get/api/mcpBearer

MCP Streamable HTTP (GET SSE)

Responses

  • 200MCP SSE stream
  • 401Missing or invalid credentials
  • 429Rate limit exceeded
post/api/mcpBearer

MCP Streamable HTTP (POST JSON-RPC)

Request body

application/json

Responses

  • 200MCP response (JSON or SSE per client Accept header)
  • 401Missing or invalid credentials
  • 429Rate limit exceeded
delete/api/mcpBearer

MCP Streamable HTTP (session teardown)

Responses

  • 200OK
  • 401Missing or invalid credentials
get/.well-known/oauth-protected-resourcePublic

OAuth protected resource metadata (RFC 9728)

Responses

  • 200Metadata JSON
get/.well-known/oauth-authorization-serverPublic

OAuth authorization server metadata (RFC 8414)

Responses

  • 200Metadata JSON

Site & page JSON

These fields line up with UpdateSiteRequest in the spec. Optional keys can be omitted; sending pages replaces the entire page array, while theme merges shallowly.

  • title — public site name
  • description, socialImageUrl — default SEO
  • faviconUrl, headScripts
  • pages SitePageDef[]
  • theme SiteTheme

One page in pages[]

Name in API spec: SitePageDef

FieldRequiredType / constraints
blocksyesarray[→ PageBlock]
dynamicno→ SitePageDynamic
seono→ SitePageSeo
slugyesstring
titlenostring

Global theme object

Name in API spec: SiteTheme

FieldRequiredType / constraints
backgroundnostring — CSS hex color, e.g. #27272a
bordernostring — CSS hex color, e.g. #27272a
borderRadiusnonone, sm, md
fontPresetnointer, poppins, roboto, open-sans, lato, montserrat, raleway, dm-sans, space-grotesk, outfit, plus-jakarta-sans, playfair-display, …
footerBackgroundnostring — CSS hex color, e.g. #27272a
footerForegroundnostring — CSS hex color, e.g. #27272a
footerMutednostring — CSS hex color, e.g. #27272a
foregroundnostring — CSS hex color, e.g. #27272a
headingFontPresetnointer, poppins, roboto, open-sans, lato, montserrat, raleway, dm-sans, space-grotesk, outfit, plus-jakarta-sans, playfair-display, …
heroForegroundnostring — CSS hex color, e.g. #27272a
heroFromnostring — CSS hex color, e.g. #27272a
heroTonostring — CSS hex color, e.g. #27272a
mutednostring — CSS hex color, e.g. #27272a
mutedForegroundnostring — CSS hex color, e.g. #27272a
primarynostring — CSS hex color, e.g. #27272a
primaryForegroundnostring — CSS hex color, e.g. #27272a
sectionSpacingnocompact, default, spacious

Section types (blocks)

Each block has a type discriminator plus props. Optional anchorId becomes the HTML id for in-page links like #pricing. Optional fullWidth, colorOverrides, and animation apply to every block type (see schema BlockAnimation in the OpenAPI components). Presets include fade, slide, zoom, blur, and stagger; stagger animates direct child elements in sequence. Respect for reduced motion is handled in published CSS.

Layout

  • navbar

    NavigationTop bar with your brand, links, and optional CTA.

    NavbarBlockProps

    FieldRequiredType / constraints
    brandLabelyesstring
    ctaHrefnostring
    ctaIconnostring — Lucide icon id (optional).
    ctaLabelnostring
    linksyesarray[→ NavLinkItem]
    logoIconnostring — Lucide icon id when logoUrl is empty (e.g. sparkles). Prefer for API-generated sites without a logo asset.
    logoUrlnostring — Public image URL (e.g. from POST /api/v1/media/upload).
    variantnostandard, minimal, elevated, dense, splitCentered
  • hero

    HeroHeadline, CTAs, imagery — background fill (gradient, solid, photo), patterns, splits, stacked/full-bleed/centered with optional below-fold image, trust row, highlights.

    HeroBlockProps

    FieldRequiredType / constraints
    announcementHrefnostring — Optional link for the announcement pill.
    announcementTextnostring — Optional pill above eyebrow (e.g. funding news).
    backgroundFillnothemeGradientBand, solidPageBackground, photoWithThemeTint
    backgroundImagePositionnocenter, top, bottom, left, right, top left, top right, bottom left, bottom right
    backgroundImageUrlnostring
    backgroundPatternnonone, subtleLineGrid, subtleDotGrid, diagonalFineLines, radialCornerWash
    copyEntrancenonone, fadeRise
    eyebrownostring — Optional short label above the headline.
    featuredImageAltnostring
    featuredImageFitnocover, contain
    featuredImagePositionnocenter, top, bottom, left, right, top left, top right, bottom left, bottom right
    featuredImageUrlnostring
    featuredPresentationnobanner, mockup
    featuredTiltnoboolean — When featuredPresentation is mockup, apply a subtle 3D tilt (respects reduced motion).
    headlineyesstring
    headlineEmphasisnostring — Substring of headline to emphasize (gradient or outlined box); first match only.
    headlineEmphasisStylenoaccentGradientText, softBadgeOutline, thickUnderlineAccent, translucentMarker, solidAccentPill
    highlightsnoarray[→ HeroHighlightItem]
    primaryCtaHrefyesstring
    primaryCtaIconnostring
    primaryCtaLabelyesstring
    secondaryCtaHrefyesstring
    secondaryCtaIconnostring
    secondaryCtaLabelyesstring
    secondaryCtaVariantnooutline, text
    subheadlineyesstring
    trustCaptionnostring — Small caption above trust logos (e.g. “Trusted by”).
    trustItemsnoarray[→ HeroTrustItem]
    variantnomarketingCenteredGradient, marketingCenteredSolid, splitTextLeftImageRight, splitImageLeftTextRight, stackedCenteredWithWideImageBelow, editorialStart
  • animatedHero

    Animated heroHero with animated gradient, optional word marquee, and floating shapes — extends the standard hero.

  • banner

    Announcement bannerThin announcement or notification strip with optional link and icon.

    BannerBlockProps

    FieldRequiredType / constraints
    dismissiblenoboolean
    hrefnostring
    iconnostring — Lucide icon id (optional).
    linkLabelnostring
    textyesstring
    variantnoinfo, success, warning, accent
  • split

    Split columnsTwo columns for compare-and-contrast stories.

    SplitBlockProps

    FieldRequiredType / constraints
    asideBodyyesstring
    asideHeadingyesstring
    bodyyesstring
    headingyesstring
  • imageText

    Image & textPhoto or graphic beside a headline and body copy.

    ImageTextBlockProps

    FieldRequiredType / constraints
    bodyyesstring
    headingyesstring
    imageAltyesstring
    imageFitnocover, contain
    imagePositionnocenter, top, bottom, left, right, top left, top right, bottom left, bottom right
    imageSideyesleft, right
    imageUrlyesstring
  • bentoFeatures

    Bento gridAsymmetric feature cells in a bento-style grid.

    BentoFeaturesBlockProps

    FieldRequiredType / constraints
    cellsyesarray[→ BentoCell]
    headingyesstring
  • featureShowcase

    Feature showcaseSticky scroll feature sections with alternating media and bullet lists.

    FeatureShowcaseBlockProps

    FieldRequiredType / constraints
    headingnostring
    itemsyesarray[→ FeatureShowcaseItem]
    mediaSidenoleft, right, alternate
    stickyScrollnoboolean

Content

  • text

    Text sectionSimple heading plus paragraph—great for policy or bios.

    TextBlockProps

    FieldRequiredType / constraints
    bodyyesstring
    headingyesstring
  • rich

    Rich blockLong-form content with headings, lists, and formatting.

    RichBlockProps

    FieldRequiredType / constraints
    docyes→ TipTapDoc
  • features

    Features gridSelling points: icon grid or alternating image rows (layout + per-item imageUrl/imageAlt), optional subheading.

    FeaturesBlockProps

    FieldRequiredType / constraints
    headingyesstring
    itemsyesarray[→ FeatureItem]
    layoutnogrid, alternating
    subheadingnostring
  • stats

    Stats rowKey metrics in a clean horizontal row.

    StatsBlockProps

    FieldRequiredType / constraints
    headingyesstring
    statsyesarray[→ StatItem]
  • metricsBand

    Metrics bandAnimated or static KPI band with count-up numbers.

    MetricsBandBlockProps

    FieldRequiredType / constraints
    countUpnoboolean
    headingnostring
    itemsyesarray[→ MetricsBandItem]
    stylenominimal, card, split
  • team

    Team gridTeam member grid with avatars, roles, bios, and social links.

    TeamBlockProps

    FieldRequiredType / constraints
    columnsyes2, 3, 4
    headingyesstring
    membersyesarray[→ TeamMember]
    subheadingnostring
  • callout

    Callout boxHighlighted callout box for tips, warnings, or important notes.

    CalloutBlockProps

    FieldRequiredType / constraints
    bodyyesstring
    headingnostring
    iconnostring — Lucide icon id; defaults to variant icon.
    variantnoinfo, tip, warning, important
  • list

    List / grid (static)Manually edited cards or rows (team, services, resources).

    ListBlockProps

    FieldRequiredType / constraints
    columnsyes2, 3, 4
    headingyesstring
    itemsyesarray[→ ListItem]
    layoutyeslist, grid
    showImagesyesboolean
  • collectionList

    CMS index blockRepeating cards loaded from a content collection (blog posts, directory, etc.).

    CollectionListBlockProps

    FieldRequiredType / constraints
    collectionIdyesstring — CMS collection id (`GET /api/v1/sites/{subdomain}/collections`).
    columnsyes2, 3, 4
    fieldMapno→ CollectionListFieldMap
    headingyesstring
    layoutyeslist, grid
    limitnointeger — Max items when pagination is disabled.
    paginationno{ enabled: boolean; pageSize: integer }
    showImagesyesboolean
    sortFieldnostring — Field id or `updatedAt`.
    sortOrdernoasc, desc
    visibleFieldsnoarray[string]
  • collectionDetail

    CMS detail blockRenders one CMS entry on detail URLs from your collection fields.

    CollectionDetailBlockProps

    FieldRequiredType / constraints
    layoutnostandard, wide, sidebar
    showDateyesboolean
    showFieldsnoarray[string]
    showImageyesboolean
    variantnoarticle, listing, profile
    visibleFieldsnoarray[string]
  • steps

    How it worksNumbered or icon steps for your process.

    StepsBlockProps

    FieldRequiredType / constraints
    headingyesstring
    stepsyesarray[→ StepItem]
    subheadingnostring
  • timeline

    TimelineMilestones, roadmap, or history.

    TimelineBlockProps

    FieldRequiredType / constraints
    headingyesstring
    itemsyesarray[→ TimelineItem]
  • comparison

    ComparisonSide-by-side comparison (not full pricing tables).

    ComparisonBlockProps

    FieldRequiredType / constraints
    headingyesstring
    leftTitleyesstring
    rightTitleyesstring
    rowsyesarray[→ ComparisonRow]
  • comparisonTable

    Comparison tableFull pricing-style comparison table with CTAs per column.

    ComparisonTableBlockProps

    FieldRequiredType / constraints
    columnsyesarray[→ ComparisonTableColumn]
    headingnostring
    rowsyesarray[→ ComparisonTableRow]
    stickyHeadernoboolean

Media

  • imageGallery

    Image galleryRows of images with optional captions.

    ImageGalleryBlockProps

    FieldRequiredType / constraints
    columnsyes2, 3, 4
    headingyesstring
    imagesyesarray[→ GalleryImage]
  • youtube

    YouTube videoResponsive embedded video player.

    YoutubeBlockProps

    FieldRequiredType / constraints
    aspectRationo16:9, 4:3, 1:1
    titlenostring
    videoUrlyesstring
  • map

    Google MapLocation map visitors can pan and zoom.

    MapBlockProps

    FieldRequiredType / constraints
    embedUrlnostring
    heightnointeger
    querynostring
    zoomnointeger
  • embed

    Custom embedDrop in calendars, widgets, or other iframe tools.

    EmbedBlockProps

    FieldRequiredType / constraints
    captionnostring
    htmlyesstring — Iframe HTML; sanitized when rendered.
    maxWidthnointeger
  • marquee

    Scrolling tickerInfinite horizontal scrolling ticker for logos, badges, or short text.

    MarqueeBlockProps

    FieldRequiredType / constraints
    directionnoleft, right
    itemsyesarray[→ MarqueeItem]
    pauseOnHovernoboolean
    speednoslow, normal, fast
  • logoCloud

    Logo cloudPartner logos in a row, grid, or infinite marquee with optional grayscale.

    LogoCloudBlockProps

    FieldRequiredType / constraints
    grayscalenoboolean
    itemsyesarray[→ LogoCloudItem]
    speednoslow, normal, fast
    stylenorow, marquee, grid3Rows, infiniteScroll
  • gallery3d

    3D galleryImage gallery with mosaic, parallax, tilt stack, or coverflow motion.

    Gallery3dBlockProps

    FieldRequiredType / constraints
    effectnoparallax, tiltStack, coverflow, mosaic
    headingnostring
    itemsyesarray[→ Gallery3dItem]

Engagement

  • cta

    Call to actionSingle focused pitch with one primary button; solid, outline, or muted section variant.

    CtaBlockProps

    FieldRequiredType / constraints
    bodyyesstring
    buttonHrefyesstring
    buttonIconnostring
    buttonLabelyesstring
    headingyesstring
    variantnosolid, outline, muted
  • testimonial

    TestimonialCustomer quote with name and role.

    TestimonialBlockProps

    FieldRequiredType / constraints
    authoryesstring
    imageUrlnostring — Optional avatar image URL.
    quoteyesstring
    roleyesstring
  • testimonials

    TestimonialsMultiple quotes: grid, featured (first quote large), or marquee layout.

    TestimonialsBlockProps

    FieldRequiredType / constraints
    headingnostring
    itemsyesarray[→ TestimonialsItem]
    layoutnogrid, featured, marquee
  • faq

    FAQAccordion-style questions and answers.

    FaqBlockProps

    FieldRequiredType / constraints
    headingyesstring
    itemsyesarray[→ FaqItem]
  • faqAccordion

    FAQ accordionNative accordion FAQ with grouped, flat, or two-column layout.

    FaqAccordionBlockProps

    FieldRequiredType / constraints
    allowMultiplenoboolean
    headingnostring
    itemsyesarray[→ FaqAccordionItem]
    startOpenIndexnointeger
    stylenogrouped, flat, twoColumn
  • logos

    Logo stripPartner or press logos: text names and/or optional image URLs per logo.

    LogosBlockProps

    FieldRequiredType / constraints
    headingyesstring
    logosnoarray[→ LogoStripItem]
    namesnoarray[string]
  • pricing

    PricingPlans with prices, bullets, and sign-up buttons.

    PricingBlockProps

    FieldRequiredType / constraints
    headingyesstring
    subheadingnostring
    tiersyesarray[→ PricingTier]
  • newsletter

    Newsletter signupEmail capture section with heading, inline input, and submit button.

    NewsletterBlockProps

    FieldRequiredType / constraints
    buttonIconnostring — Lucide icon id (optional).
    buttonLabelyesstring
    descriptionnostring
    headingyesstring
    inputPlaceholderyesstring
    successMessageyesstring
    variantnoinline, stacked
  • form

    Form (collect responses)Collect leads and messages—submissions land in your dashboard.

    FormBlockProps

    FieldRequiredType / constraints
    descriptionnostring
    fieldsyesarray[→ FormField]
    formNameyesstring — Human-facing title on the page and in submissions (e.g. Contact us). Avoid snake_case internal ids.
    submitIconnostring
    submitLabelyesstring
    successMessageyesstring

Structure

  • divider

    Divider / spacerBreathing room, line, or spacer between sections.

    DividerBlockProps

    FieldRequiredType / constraints
    heightPxnointeger — Used when variant is blank.
    variantyesline, dotted, blank
  • footer

    FooterBottom links, socials, and copyright.

    FooterBlockProps

    FieldRequiredType / constraints
    brandyesstring
    columnsnoarray[→ FooterColumn]
    copyrightYearnointeger
    socialLinksnoarray[→ SocialLink]
    taglineyesstring
  • section

    Custom HTMLPaste or write HTML and optional scoped CSS for layouts that are not covered by standard blocks. Optional AI assist to generate markup.

    SectionBlockProps

    FieldRequiredType / constraints
    cssnostring — Optional scoped CSS; selectors start with .ai-custom-root (or .in-view .ai-custom-root).
    generationModelnostring — Model id used for last generation (informational).
    htmlyesstring — Sanitized HTML fragment; Tailwind and theme CSS variables. No script/iframe/form/button.
    intentnostring — Semantic hint when using optional AI assist on this block.
    labelyesstring — Display name in the editor block list.
    promptnostring — Authoring prompt for generate/regenerate.

Template IDs

GET /api/v1/templates includes previewImageUrl for each id — a site-relative WebP path under /images/builtin-templates/.

  • aiSaasAnimated hero, logo marquee, bento grid, sticky feature story, metrics, pricing, and FAQ.
  • financialAdvisorTrust-first layout with process steps, team, testimonials, and a consultation form.
  • lawFirmPractice areas, firm timeline, partners, client outcomes, and consultation CTA.
  • medicalAestheticClinical hero, treatment bento, gallery, membership pricing, and booking form.
  • realEstatePhoto hero, KPI band, listing gallery, bio split, press logos, and inquiry form.
  • executiveCoachPremium hero, client logos, transformation pillars, offers, and application form.
  • agencyBold hero, case-study gallery, process, metrics, team, and project CTA.
  • boutiqueHotelImmersive hero, rooms gallery, amenities, story, map, and booking inquiry.
  • weddingVenueEditorial hero, event gallery, planning steps, packages, FAQ, and tour form.
  • interiorDesignPortfolio-forward hero, project grid, philosophy, process, press, and contact.
  • dtcProductLaunch hero, proof metrics, bento highlights, lifestyle gallery, comparison table.
  • onlineCourseAnimated hero, student metrics, module showcase, curriculum timeline, pricing.
  • fineDiningEditorial hero, menu rich text, photography, press quotes, map, and reservations.
  • luxuryPortfolioSplit hero, curated gallery, about split, testimonial, clients, inquiry form.
  • comingSoonMinimal launch page with stats and newsletter capture.

Errors

Bodies are JSON like { "error": "…" }. Expect 400 for validation, 401 for auth, 403 for ownership or plan limits, 404 when a resource is missing, 409 for conflicts, 429 when throttled, and 502/503 if an upstream integration is unavailable.

Schema names in OpenAPI

Block props use these component schema names: NavbarBlockProps, HeroBlockProps, AnimatedHeroBlockProps, BannerBlockProps, SplitBlockProps, ImageTextBlockProps, BentoFeaturesBlockProps, FeatureShowcaseBlockProps, TextBlockProps, RichBlockProps, FeaturesBlockProps, StatsBlockProps, MetricsBandBlockProps, TeamBlockProps, CalloutBlockProps, ListBlockProps, CollectionListBlockProps, CollectionDetailBlockProps, StepsBlockProps, TimelineBlockProps, ComparisonBlockProps, ComparisonTableBlockProps, ImageGalleryBlockProps, YoutubeBlockProps, MapBlockProps, EmbedBlockProps, MarqueeBlockProps, LogoCloudBlockProps, Gallery3dBlockProps, CtaBlockProps, TestimonialBlockProps, TestimonialsBlockProps, FaqBlockProps, FaqAccordionBlockProps, LogosBlockProps, PricingBlockProps, NewsletterBlockProps, FormBlockProps, DividerBlockProps, FooterBlockProps, SectionBlockProps. Shared helpers include NavLinkItem, FormField, SitePageDynamic, and TipTapDoc.

Copy-paste examples

Swap in your real subdomain where you see my-site, use a live API key from the dashboard, and pick the language tab you prefer. If you are already signed in on this site in a browser, your session cookie works too—no header required for the same routes.

Send the Authorization header

Every authenticated route expects Bearer auth unless you rely on a browser session.

Authorization: Bearer YOUR_API_KEY

List sites in the active workspace

Returns every site your current key or session can manage.

curl -sS "https://slatehut.com/api/v1/sites" \
  -H "Authorization: Bearer YOUR_KEY"

Create a site from a single prompt (AI)

Runs planning plus one home page, then persists like POST /api/v1/sites. Uses workspace AI credits.

curl -sS -X POST "https://slatehut.com/api/v1/sites/generate" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"A consulting firm with services, team, and contact form"}'

AI step 1 — get a plan JSON you can edit

Non-streaming JSON with a top-level plan object. Review or change it, then call /generate/from-plan.

curl -sS -X POST "https://slatehut.com/api/v1/sites/generate/plan" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"A consulting firm with services, team, and contact form"}'

AI step 2 — persist the site from a plan response

POST the same JSON body you received from /generate/plan (it includes the plan field).

curl -sS -X POST "https://slatehut.com/api/v1/sites/generate/from-plan" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d @plan-response.json

Fetch the full site document

Includes pages, blocks, theme, and metadata for one subdomain.

curl -sS "https://slatehut.com/api/v1/sites/my-site" \
  -H "Authorization: Bearer YOUR_KEY"

Update site title and merge theme

Theme keys merge shallowly. Sending pages replaces the entire list when present.

curl -sS -X PUT "https://slatehut.com/api/v1/sites/my-site" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"Studio North","theme":{"radius":"md"}}'

List pages and read the home page

Home uses the path segment underscore, not the word home.

curl -sS "https://slatehut.com/api/v1/sites/my-site/pages" \
  -H "Authorization: Bearer YOUR_KEY"

curl -sS "https://slatehut.com/api/v1/sites/my-site/pages/_" \
  -H "Authorization: Bearer YOUR_KEY"

List blocks on the home page

Swap _ for another encoded page path when you target nested routes.

curl -sS "https://slatehut.com/api/v1/sites/my-site/pages/_/blocks" \
  -H "Authorization: Bearer YOUR_KEY"

Upload an image or file

Multipart field name must be file. Use the returned URL inside block props.

curl -sS -X POST "https://slatehut.com/api/v1/media/upload" \
  -H "Authorization: Bearer YOUR_KEY" \
  -F "file=@./photo.jpg"

Import a photo from Unsplash

Requires Unsplash to be configured on the server. Returns url and alt text.

curl -sS -X POST "https://slatehut.com/api/v1/media/unsplash/import" \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"photoId":"UNSPLASH_PHOTO_ID"}'

Check whether a subdomain is free

Helpful before you create a new site through the API.

curl -sS "https://slatehut.com/api/v1/sites/availability?q=my-brand" \
  -H "Authorization: Bearer YOUR_KEY"

Download the live OpenAPI document

Public route—no auth required. Save it for codegen or import into Postman.

curl -sS "https://slatehut.com/api/v1/openapi.json"