/api/v1/openapi.jsonPublicOpenAPI document
Responses
- 200 — This OpenAPI JSON
On this page
Home / Documentation / 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.
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.
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
All versioned routes hang off your SlateHut host.
https://slatehut.com/api/v1Rate limits
Up to 60 requests per minute for each API key or session. Expect 429 when you exceed that window.
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.
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.
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 →
create_site — AI generation from a promptcreate_site_from_template — non-AI template sitelist_sites, get_site, update_site_themeadd_page, update_page, delete_pagelist_templates, check_subdomainCanned 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.
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.
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.GET /api/v1/sites/{subdomain}/pages lists routes; GET …/pages/_ returns the home document with blocks.POST …/blocks, update with PUT …/blocks/{id}, or reorder via PATCH …/blocks/reorder. Use the Data models section for props per block type.POST /api/v1/media/upload accepts multipart files; reference the returned URL inside hero, gallery, or rich blocks.PUT /api/v1/sites/{subdomain} with a theme object merges into the existing palette.Need raw HTTP samples? Jump to the Examples.
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.
/api/v1/openapi.jsonPublicResponses
/api/v1/templatesPublicResponses
/api/v1/cms/presetsPublicResponses
/api/v1/sitesBearerResponses
/api/v1/sitesBearerRequest body
application/json · CreateSiteRequest
Responses
/api/v1/sites/generateBearerRuns 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
/api/v1/sites/generate/planBearerReturns 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
/api/v1/sites/generate/from-planBearerGenerates 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
/api/v1/sites/availabilityBearerSame rules as the editor: normalization, reserved names, length 2–48, uniqueness. Empty q returns { normalized: "", available: true }.
Parameters
| Name | In | Req | Details |
|---|---|---|---|
| q | query | no | stringProposed subdomain string |
Responses
/api/v1/sites/{subdomain}BearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| include | query | no | stringComma-separated projection: pages, theme, chrome, title, description, meta, or all (default full document). |
Responses
/api/v1/sites/{subdomain}BearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
Request body
application/json · required · UpdateSiteRequest
Responses
/api/v1/sites/{subdomain}BearerPermanently 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
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
Responses
/api/v1/sites/{subdomain}/pagesBearerReturns a lightweight summary per page. Full SitePageDef is available via GET …/pages/{pagePath}.
Parameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
Responses
/api/v1/sites/{subdomain}/pagesBearerAdds 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
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
Request body
application/json · required · CreateSitePageRequest
Responses
/api/v1/sites/{subdomain}/pages/{pagePath}BearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| pagePath | path | yes | stringSingle URL segment for the page slug. Use `_` for home (`slug === ""`). Nested slugs: encode slashes, e.g. `legal%2Fprivacy`. |
Responses
/api/v1/sites/{subdomain}/pages/{pagePath}BearerPartial update: omit fields to keep current values. Set dynamic to null to remove CMS wiring. seo can be set to null to clear.
Parameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| pagePath | path | yes | stringSingle 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
/api/v1/sites/{subdomain}/pages/{pagePath}BearerCannot delete the home page or the only remaining page.
Parameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| pagePath | path | yes | stringSingle URL segment for the page slug. Use `_` for home (`slug === ""`). Nested slugs: encode slashes, e.g. `legal%2Fprivacy`. |
Responses
/api/v1/sites/{subdomain}/pages/{pagePath}/blocksBearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| pagePath | path | yes | stringSame as single-page GET: `_` = home; nested = encodeURIComponent. |
| scope | query | no | index | template`index` (default) = page `blocks`. `template` = `dynamic.templateBlocks` on CMS pages. |
Responses
/api/v1/sites/{subdomain}/pages/{pagePath}/blocksBearerOptional position (0-based insert index; default append).
Parameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| pagePath | path | yes | stringSame as single-page GET: `_` = home; nested = encodeURIComponent. |
| scope | query | no | index | template`index` (default) = page `blocks`. `template` = `dynamic.templateBlocks` on CMS pages. |
Request body
application/json · required · AddSiteBlockRequest
Responses
/api/v1/sites/{subdomain}/pages/{pagePath}/blocks/reorderBearerblockIds must list every block id exactly once.
Parameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| pagePath | path | yes | string |
| scope | query | no | index | template |
Request body
application/json · required · ReorderBlocksRequest
Responses
/api/v1/sites/{subdomain}/pages/{pagePath}/blocks/{blockId}BearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| pagePath | path | yes | string |
| blockId | path | yes | string |
| scope | query | no | index | template |
Responses
/api/v1/sites/{subdomain}/pages/{pagePath}/blocks/{blockId}BearerShallow-merge props onto existing props. anchorId / colorOverrides null clears. type and id cannot be changed.
Parameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| pagePath | path | yes | string |
| blockId | path | yes | string |
| scope | query | no | index | template |
Request body
application/json · required · BlockPatchRequest
Responses
/api/v1/sites/{subdomain}/pages/{pagePath}/blocks/{blockId}BearerCannot remove the last block on a page or template.
Parameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| pagePath | path | yes | string |
| blockId | path | yes | string |
| scope | query | no | index | template |
Responses
/api/v1/sites/{subdomain}/sync-chromeBearerCopies 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
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
Request body
application/json
Responses
/api/v1/sites/{subdomain}/preview-tokenBearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
Responses
/api/v1/sites/{subdomain}/collectionsBearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
Responses
/api/v1/sites/{subdomain}/collectionsBearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
Request body
application/json · CreateCollectionRequest
Responses
/api/v1/sites/{subdomain}/collections/{collectionId}BearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| collectionId | path | yes | string |
Responses
/api/v1/sites/{subdomain}/collections/{collectionId}BearerCannot 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
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| collectionId | path | yes | string |
Request body
application/json · required
Responses
/api/v1/sites/{subdomain}/collections/{collectionId}BearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| collectionId | path | yes | string |
Responses
/api/v1/sites/{subdomain}/collections/{collectionId}/attach-dynamic-pageBearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| collectionId | path | yes | string |
Request body
application/json · required · AttachDynamicPageRequest
Responses
/api/v1/sites/{subdomain}/collections/{collectionId}/itemsBearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| collectionId | path | yes | string |
Responses
/api/v1/sites/{subdomain}/collections/{collectionId}/itemsBearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| collectionId | path | yes | string |
Request body
application/json · required · CmsItemWriteRequest
Responses
/api/v1/sites/{subdomain}/collections/{collectionId}/items/{itemId}BearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| collectionId | path | yes | string |
| itemId | path | yes | string |
Responses
/api/v1/sites/{subdomain}/collections/{collectionId}/items/{itemId}BearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| collectionId | path | yes | string |
| itemId | path | yes | string |
Request body
application/json · required · CmsItemWriteRequest
Responses
/api/v1/sites/{subdomain}/collections/{collectionId}/items/{itemId}BearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| collectionId | path | yes | string |
| itemId | path | yes | string |
Responses
/api/v1/sites/{subdomain}/domainsBearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
Responses
/api/v1/sites/{subdomain}/domainsBearerRegisters 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
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
Request body
application/json · required
Responses
/api/v1/sites/{subdomain}/domains/{hostname}BearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| hostname | path | yes | stringURL-encoded hostname (e.g. encodeURIComponent) |
Responses
/api/v1/sites/{subdomain}/domains/{hostname}/verifyBearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| hostname | path | yes | string |
Responses
/api/v1/media/uploadBearerMultipart 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
/api/v1/submissionsBearerCross-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
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | query | no | stringOptional; restrict to this site subdomain |
| cursor | query | no | stringPagination: prior `nextCursor` (numeric submittedAt) |
Responses
/api/v1/sites/{subdomain}/submissionsBearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| formBlockId | query | no | stringOptional; filter to one block id from site JSON (`form` or `newsletter` block) |
| cursor | query | no | stringPagination: prior `nextCursor` |
Responses
/api/v1/sites/{subdomain}/submissions/countsBearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
Responses
/api/v1/sites/{subdomain}/submissions/{submissionId}BearerParameters
| Name | In | Req | Details |
|---|---|---|---|
| subdomain | path | yes | string |
| submissionId | path | yes | string |
Responses
/api/v1/media/unsplash/searchBearerQuery params: q (search text), page (1-based), optional orientation (landscape|portrait|squarish), optional color (black_and_white|black|white|yellow|orange|red|purple|magenta|green|teal|blue). If UNSPLASH_ACCESS_KEY is unset, returns unsplashConfigured: false and empty results.
Parameters
| Name | In | Req | Details |
|---|---|---|---|
| q | query | no | string |
| page | query | no | integer |
| orientation | query | no | landscape | portrait | squarish |
| color | query | no | black_and_white | black | white | yellow | orange | red | purple | magenta | green | teal | blue |
Responses
/api/v1/media/unsplash/importBearerTriggers 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
/api/v1/billing/checkoutBearerReturns 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
/api/v1/billing/portalBearerResponses
/api/v1/billing/statusBearerResponses
/api/mcpBearerResponses
/api/mcpBearerRequest body
application/json
Responses
/api/mcpBearerResponses
/.well-known/oauth-protected-resourcePublicResponses
/.well-known/oauth-authorization-serverPublicResponses
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 namedescription, socialImageUrl — default SEOfaviconUrl, headScriptspages — SitePageDef[]theme — SiteThemeName in API spec: SitePageDef
| Field | Required | Type / constraints |
|---|---|---|
| blocks | yes | array[→ PageBlock] |
| dynamic | no | → SitePageDynamic |
| seo | no | → SitePageSeo |
| slug | yes | string |
| title | no | string |
Name in API spec: SiteTheme
| Field | Required | Type / constraints |
|---|---|---|
| background | no | string — CSS hex color, e.g. #27272a |
| border | no | string — CSS hex color, e.g. #27272a |
| borderRadius | no | none, sm, md |
| fontPreset | no | inter, poppins, roboto, open-sans, lato, montserrat, raleway, dm-sans, space-grotesk, outfit, plus-jakarta-sans, playfair-display, … |
| footerBackground | no | string — CSS hex color, e.g. #27272a |
| footerForeground | no | string — CSS hex color, e.g. #27272a |
| footerMuted | no | string — CSS hex color, e.g. #27272a |
| foreground | no | string — CSS hex color, e.g. #27272a |
| headingFontPreset | no | inter, poppins, roboto, open-sans, lato, montserrat, raleway, dm-sans, space-grotesk, outfit, plus-jakarta-sans, playfair-display, … |
| heroForeground | no | string — CSS hex color, e.g. #27272a |
| heroFrom | no | string — CSS hex color, e.g. #27272a |
| heroTo | no | string — CSS hex color, e.g. #27272a |
| muted | no | string — CSS hex color, e.g. #27272a |
| mutedForeground | no | string — CSS hex color, e.g. #27272a |
| primary | no | string — CSS hex color, e.g. #27272a |
| primaryForeground | no | string — CSS hex color, e.g. #27272a |
| sectionSpacing | no | compact, default, spacious |
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.
navbar
Navigation — Top bar with your brand, links, and optional CTA.
| Field | Required | Type / constraints |
|---|---|---|
| brandLabel | yes | string |
| ctaHref | no | string |
| ctaIcon | no | string — Lucide icon id (optional). |
| ctaLabel | no | string |
| links | yes | array[→ NavLinkItem] |
| logoIcon | no | string — Lucide icon id when logoUrl is empty (e.g. sparkles). Prefer for API-generated sites without a logo asset. |
| logoUrl | no | string — Public image URL (e.g. from POST /api/v1/media/upload). |
| variant | no | standard, minimal, elevated, dense, splitCentered |
hero
Hero — Headline, CTAs, imagery — background fill (gradient, solid, photo), patterns, splits, stacked/full-bleed/centered with optional below-fold image, trust row, highlights.
| Field | Required | Type / constraints |
|---|---|---|
| announcementHref | no | string — Optional link for the announcement pill. |
| announcementText | no | string — Optional pill above eyebrow (e.g. funding news). |
| backgroundFill | no | themeGradientBand, solidPageBackground, photoWithThemeTint |
| backgroundImagePosition | no | center, top, bottom, left, right, top left, top right, bottom left, bottom right |
| backgroundImageUrl | no | string |
| backgroundPattern | no | none, subtleLineGrid, subtleDotGrid, diagonalFineLines, radialCornerWash |
| copyEntrance | no | none, fadeRise |
| eyebrow | no | string — Optional short label above the headline. |
| featuredImageAlt | no | string |
| featuredImageFit | no | cover, contain |
| featuredImagePosition | no | center, top, bottom, left, right, top left, top right, bottom left, bottom right |
| featuredImageUrl | no | string |
| featuredPresentation | no | banner, mockup |
| featuredTilt | no | boolean — When featuredPresentation is mockup, apply a subtle 3D tilt (respects reduced motion). |
| headline | yes | string |
| headlineEmphasis | no | string — Substring of headline to emphasize (gradient or outlined box); first match only. |
| headlineEmphasisStyle | no | accentGradientText, softBadgeOutline, thickUnderlineAccent, translucentMarker, solidAccentPill |
| highlights | no | array[→ HeroHighlightItem] |
| primaryCtaHref | yes | string |
| primaryCtaIcon | no | string |
| primaryCtaLabel | yes | string |
| secondaryCtaHref | yes | string |
| secondaryCtaIcon | no | string |
| secondaryCtaLabel | yes | string |
| secondaryCtaVariant | no | outline, text |
| subheadline | yes | string |
| trustCaption | no | string — Small caption above trust logos (e.g. “Trusted by”). |
| trustItems | no | array[→ HeroTrustItem] |
| variant | no | marketingCenteredGradient, marketingCenteredSolid, splitTextLeftImageRight, splitImageLeftTextRight, stackedCenteredWithWideImageBelow, editorialStart |
animatedHero
Animated hero — Hero with animated gradient, optional word marquee, and floating shapes — extends the standard hero.
banner
Announcement banner — Thin announcement or notification strip with optional link and icon.
| Field | Required | Type / constraints |
|---|---|---|
| dismissible | no | boolean |
| href | no | string |
| icon | no | string — Lucide icon id (optional). |
| linkLabel | no | string |
| text | yes | string |
| variant | no | info, success, warning, accent |
split
Split columns — Two columns for compare-and-contrast stories.
| Field | Required | Type / constraints |
|---|---|---|
| asideBody | yes | string |
| asideHeading | yes | string |
| body | yes | string |
| heading | yes | string |
imageText
Image & text — Photo or graphic beside a headline and body copy.
| Field | Required | Type / constraints |
|---|---|---|
| body | yes | string |
| heading | yes | string |
| imageAlt | yes | string |
| imageFit | no | cover, contain |
| imagePosition | no | center, top, bottom, left, right, top left, top right, bottom left, bottom right |
| imageSide | yes | left, right |
| imageUrl | yes | string |
bentoFeatures
Bento grid — Asymmetric feature cells in a bento-style grid.
| Field | Required | Type / constraints |
|---|---|---|
| cells | yes | array[→ BentoCell] |
| heading | yes | string |
featureShowcase
Feature showcase — Sticky scroll feature sections with alternating media and bullet lists.
| Field | Required | Type / constraints |
|---|---|---|
| heading | no | string |
| items | yes | array[→ FeatureShowcaseItem] |
| mediaSide | no | left, right, alternate |
| stickyScroll | no | boolean |
text
Text section — Simple heading plus paragraph—great for policy or bios.
| Field | Required | Type / constraints |
|---|---|---|
| body | yes | string |
| heading | yes | string |
rich
Rich block — Long-form content with headings, lists, and formatting.
| Field | Required | Type / constraints |
|---|---|---|
| doc | yes | → TipTapDoc |
features
Features grid — Selling points: icon grid or alternating image rows (layout + per-item imageUrl/imageAlt), optional subheading.
| Field | Required | Type / constraints |
|---|---|---|
| heading | yes | string |
| items | yes | array[→ FeatureItem] |
| layout | no | grid, alternating |
| subheading | no | string |
stats
Stats row — Key metrics in a clean horizontal row.
| Field | Required | Type / constraints |
|---|---|---|
| heading | yes | string |
| stats | yes | array[→ StatItem] |
metricsBand
Metrics band — Animated or static KPI band with count-up numbers.
| Field | Required | Type / constraints |
|---|---|---|
| countUp | no | boolean |
| heading | no | string |
| items | yes | array[→ MetricsBandItem] |
| style | no | minimal, card, split |
team
Team grid — Team member grid with avatars, roles, bios, and social links.
| Field | Required | Type / constraints |
|---|---|---|
| columns | yes | 2, 3, 4 |
| heading | yes | string |
| members | yes | array[→ TeamMember] |
| subheading | no | string |
callout
Callout box — Highlighted callout box for tips, warnings, or important notes.
| Field | Required | Type / constraints |
|---|---|---|
| body | yes | string |
| heading | no | string |
| icon | no | string — Lucide icon id; defaults to variant icon. |
| variant | no | info, tip, warning, important |
list
List / grid (static) — Manually edited cards or rows (team, services, resources).
| Field | Required | Type / constraints |
|---|---|---|
| columns | yes | 2, 3, 4 |
| heading | yes | string |
| items | yes | array[→ ListItem] |
| layout | yes | list, grid |
| showImages | yes | boolean |
collectionList
CMS index block — Repeating cards loaded from a content collection (blog posts, directory, etc.).
| Field | Required | Type / constraints |
|---|---|---|
| collectionId | yes | string — CMS collection id (`GET /api/v1/sites/{subdomain}/collections`). |
| columns | yes | 2, 3, 4 |
| fieldMap | no | → CollectionListFieldMap |
| heading | yes | string |
| layout | yes | list, grid |
| limit | no | integer — Max items when pagination is disabled. |
| pagination | no | { enabled: boolean; pageSize: integer } |
| showImages | yes | boolean |
| sortField | no | string — Field id or `updatedAt`. |
| sortOrder | no | asc, desc |
| visibleFields | no | array[string] |
collectionDetail
CMS detail block — Renders one CMS entry on detail URLs from your collection fields.
| Field | Required | Type / constraints |
|---|---|---|
| layout | no | standard, wide, sidebar |
| showDate | yes | boolean |
| showFields | no | array[string] |
| showImage | yes | boolean |
| variant | no | article, listing, profile |
| visibleFields | no | array[string] |
steps
How it works — Numbered or icon steps for your process.
| Field | Required | Type / constraints |
|---|---|---|
| heading | yes | string |
| steps | yes | array[→ StepItem] |
| subheading | no | string |
timeline
Timeline — Milestones, roadmap, or history.
| Field | Required | Type / constraints |
|---|---|---|
| heading | yes | string |
| items | yes | array[→ TimelineItem] |
comparison
Comparison — Side-by-side comparison (not full pricing tables).
| Field | Required | Type / constraints |
|---|---|---|
| heading | yes | string |
| leftTitle | yes | string |
| rightTitle | yes | string |
| rows | yes | array[→ ComparisonRow] |
comparisonTable
Comparison table — Full pricing-style comparison table with CTAs per column.
| Field | Required | Type / constraints |
|---|---|---|
| columns | yes | array[→ ComparisonTableColumn] |
| heading | no | string |
| rows | yes | array[→ ComparisonTableRow] |
| stickyHeader | no | boolean |
imageGallery
Image gallery — Rows of images with optional captions.
| Field | Required | Type / constraints |
|---|---|---|
| columns | yes | 2, 3, 4 |
| heading | yes | string |
| images | yes | array[→ GalleryImage] |
youtube
YouTube video — Responsive embedded video player.
| Field | Required | Type / constraints |
|---|---|---|
| aspectRatio | no | 16:9, 4:3, 1:1 |
| title | no | string |
| videoUrl | yes | string |
map
Google Map — Location map visitors can pan and zoom.
| Field | Required | Type / constraints |
|---|---|---|
| embedUrl | no | string |
| height | no | integer |
| query | no | string |
| zoom | no | integer |
embed
Custom embed — Drop in calendars, widgets, or other iframe tools.
| Field | Required | Type / constraints |
|---|---|---|
| caption | no | string |
| html | yes | string — Iframe HTML; sanitized when rendered. |
| maxWidth | no | integer |
marquee
Scrolling ticker — Infinite horizontal scrolling ticker for logos, badges, or short text.
| Field | Required | Type / constraints |
|---|---|---|
| direction | no | left, right |
| items | yes | array[→ MarqueeItem] |
| pauseOnHover | no | boolean |
| speed | no | slow, normal, fast |
logoCloud
Logo cloud — Partner logos in a row, grid, or infinite marquee with optional grayscale.
| Field | Required | Type / constraints |
|---|---|---|
| grayscale | no | boolean |
| items | yes | array[→ LogoCloudItem] |
| speed | no | slow, normal, fast |
| style | no | row, marquee, grid3Rows, infiniteScroll |
gallery3d
3D gallery — Image gallery with mosaic, parallax, tilt stack, or coverflow motion.
| Field | Required | Type / constraints |
|---|---|---|
| effect | no | parallax, tiltStack, coverflow, mosaic |
| heading | no | string |
| items | yes | array[→ Gallery3dItem] |
cta
Call to action — Single focused pitch with one primary button; solid, outline, or muted section variant.
| Field | Required | Type / constraints |
|---|---|---|
| body | yes | string |
| buttonHref | yes | string |
| buttonIcon | no | string |
| buttonLabel | yes | string |
| heading | yes | string |
| variant | no | solid, outline, muted |
testimonial
Testimonial — Customer quote with name and role.
| Field | Required | Type / constraints |
|---|---|---|
| author | yes | string |
| imageUrl | no | string — Optional avatar image URL. |
| quote | yes | string |
| role | yes | string |
testimonials
Testimonials — Multiple quotes: grid, featured (first quote large), or marquee layout.
| Field | Required | Type / constraints |
|---|---|---|
| heading | no | string |
| items | yes | array[→ TestimonialsItem] |
| layout | no | grid, featured, marquee |
faq
FAQ — Accordion-style questions and answers.
| Field | Required | Type / constraints |
|---|---|---|
| heading | yes | string |
| items | yes | array[→ FaqItem] |
faqAccordion
FAQ accordion — Native accordion FAQ with grouped, flat, or two-column layout.
| Field | Required | Type / constraints |
|---|---|---|
| allowMultiple | no | boolean |
| heading | no | string |
| items | yes | array[→ FaqAccordionItem] |
| startOpenIndex | no | integer |
| style | no | grouped, flat, twoColumn |
logos
Logo strip — Partner or press logos: text names and/or optional image URLs per logo.
| Field | Required | Type / constraints |
|---|---|---|
| heading | yes | string |
| logos | no | array[→ LogoStripItem] |
| names | no | array[string] |
pricing
Pricing — Plans with prices, bullets, and sign-up buttons.
| Field | Required | Type / constraints |
|---|---|---|
| heading | yes | string |
| subheading | no | string |
| tiers | yes | array[→ PricingTier] |
newsletter
Newsletter signup — Email capture section with heading, inline input, and submit button.
| Field | Required | Type / constraints |
|---|---|---|
| buttonIcon | no | string — Lucide icon id (optional). |
| buttonLabel | yes | string |
| description | no | string |
| heading | yes | string |
| inputPlaceholder | yes | string |
| successMessage | yes | string |
| variant | no | inline, stacked |
form
Form (collect responses) — Collect leads and messages—submissions land in your dashboard.
| Field | Required | Type / constraints |
|---|---|---|
| description | no | string |
| fields | yes | array[→ FormField] |
| formName | yes | string — Human-facing title on the page and in submissions (e.g. Contact us). Avoid snake_case internal ids. |
| submitIcon | no | string |
| submitLabel | yes | string |
| successMessage | yes | string |
divider
Divider / spacer — Breathing room, line, or spacer between sections.
| Field | Required | Type / constraints |
|---|---|---|
| heightPx | no | integer — Used when variant is blank. |
| variant | yes | line, dotted, blank |
footer
Footer — Bottom links, socials, and copyright.
| Field | Required | Type / constraints |
|---|---|---|
| brand | yes | string |
| columns | no | array[→ FooterColumn] |
| copyrightYear | no | integer |
| socialLinks | no | array[→ SocialLink] |
| tagline | yes | string |
section
Custom HTML — Paste or write HTML and optional scoped CSS for layouts that are not covered by standard blocks. Optional AI assist to generate markup.
| Field | Required | Type / constraints |
|---|---|---|
| css | no | string — Optional scoped CSS; selectors start with .ai-custom-root (or .in-view .ai-custom-root). |
| generationModel | no | string — Model id used for last generation (informational). |
| html | yes | string — Sanitized HTML fragment; Tailwind and theme CSS variables. No script/iframe/form/button. |
| intent | no | string — Semantic hint when using optional AI assist on this block. |
| label | yes | string — Display name in the editor block list. |
| prompt | no | string — Authoring prompt for generate/regenerate. |
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.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.
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.
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.
Every authenticated route expects Bearer auth unless you rely on a browser session.
Authorization: Bearer YOUR_API_KEY
Returns every site your current key or session can manage.
curl -sS "https://slatehut.com/api/v1/sites" \ -H "Authorization: Bearer YOUR_KEY"
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"}'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"}'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
Includes pages, blocks, theme, and metadata for one subdomain.
curl -sS "https://slatehut.com/api/v1/sites/my-site" \ -H "Authorization: Bearer YOUR_KEY"
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"}}'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"
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"
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"
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"}'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"
Public route—no auth required. Save it for codegen or import into Postman.
curl -sS "https://slatehut.com/api/v1/openapi.json"