Sites

GET /sites/{siteId}/brand-assets

List the images and files uploaded for a site's branding, along with how much of the storage allowance they use.

Requires the settings:read permission.

Path Parameters

siteIdstring (uuid)required

The ID of the site.

Request
curl \
  "https://api.cascade.dev/sites/550e8400-e29b-41d4-a716-446655440000/brand-assets" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY"
Response
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "string",
      "url": "string",
      "sizeBytes": 0,
      "createdAt": "2025-01-15T09:30:00Z"
    }
  ],
  "totalSizeBytes": 0,
  "limitBytes": 0
}

POST /sites/{siteId}/brand-assets

Attach an already-uploaded file to a site as a brand asset. Upload the file first with POST /files/upload-url, then pass the key it returns.

Requires the settings:write permission.

Path Parameters

siteIdstring (uuid)required

The ID of the site.

Body Parameters

keystringrequired

The storage key returned by POST /files/upload-url for the uploaded file.

Request
curl \
  -X POST \
  "https://api.cascade.dev/sites/550e8400-e29b-41d4-a716-446655440000/brand-assets" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "key": "string"
}'
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "string",
  "url": "string",
  "sizeBytes": 0,
  "createdAt": "2025-01-15T09:30:00Z"
}

DELETE /sites/{siteId}/brand-assets/{fileId}

Delete a brand asset. Anything still pointing at its URL, such as an email template, will break.

Requires the settings:write permission.

Path Parameters

siteIdstring (uuid)required

The ID of the site the asset belongs to.

fileIdstring (uuid)required

The ID of the brand asset to delete.

Request
curl \
  -X DELETE \
  "https://api.cascade.dev/sites/550e8400-e29b-41d4-a716-446655440000/brand-assets/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY"
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "string",
  "url": "string",
  "sizeBytes": 0,
  "createdAt": "2025-01-15T09:30:00Z"
}

GET /sites

List the organization's sites, alphabetically by default. Supports filtering and cursor pagination.

Requires the settings:read permission.

Query Parameters

limitnumber

The number of records to return.

cursorstring

A pagination cursor. Fetch the next page by passing the nextCursor value from the previous response.

sortname | -name | slug | -slug | createdAt | -createdAt

The sort order. Prefix a field with - to sort descending. Defaults to name.

filterstring

A JSON-encoded filter document, for example {"createdAt":{"$gte":"2025-01-01T00:00:00Z"}}. Filterable fields: id, name, slug, baseUrl, createdAt. See Filtering for the syntax.

Request
curl \
  "https://api.cascade.dev/sites" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY"
Response
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "string",
      "slug": "string",
      "baseUrl": "string",
      "brandSettings": {
        "primaryColor": "...",
        "pageColor": "...",
        "contentColor": "...",
        "textColor": "...",
        "mutedColor": "...",
        "logoUrl": "...",
        "iconUrl": "..."
      },
      "metadata": "...",
      "createdAt": "2025-01-15T09:30:00Z",
      "updatedAt": "2025-01-15T09:30:00Z"
    }
  ],
  "nextCursor": "string"
}

POST /sites

Create a site. Fails if the organization is already at its plan's site limit, or if another site already uses the slug. Triggers the site.created webhook.

Requires the settings:write permission.

Body Parameters

dataobjectrequired

The site to create.

Request
curl \
  -X POST \
  "https://api.cascade.dev/sites" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "data": {
    "name": "string",
    "slug": "string",
    "baseUrl": "https://example.com",
    "brandSettings": {
      "logoKey": "string",
      "iconKey": "string",
      "primaryColor": "string",
      "pageColor": "string",
      "contentColor": "string",
      "textColor": "string",
      "mutedColor": "string"
    },
    "metadata": "..."
  }
}'
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "string",
  "slug": "string",
  "baseUrl": "string",
  "brandSettings": {
    "primaryColor": "string",
    "pageColor": "string",
    "contentColor": "string",
    "textColor": "string",
    "mutedColor": "string",
    "logoUrl": "https://example.com",
    "iconUrl": "https://example.com"
  },
  "metadata": "...",
  "createdAt": "2025-01-15T09:30:00Z",
  "updatedAt": "2025-01-15T09:30:00Z"
}

GET /sites/{id}

Get a single site by ID.

Requires the settings:read permission.

Path Parameters

idstring (uuid)required

The ID of the site.

Request
curl \
  "https://api.cascade.dev/sites/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY"
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "string",
  "slug": "string",
  "baseUrl": "string",
  "brandSettings": {
    "primaryColor": "string",
    "pageColor": "string",
    "contentColor": "string",
    "textColor": "string",
    "mutedColor": "string",
    "logoUrl": "https://example.com",
    "iconUrl": "https://example.com"
  },
  "metadata": "...",
  "createdAt": "2025-01-15T09:30:00Z",
  "updatedAt": "2025-01-15T09:30:00Z"
}

PUT /sites/{id}

Update a site's details or branding. Fails if the new slug is already in use by another site. Triggers the site.updated webhook.

Requires the settings:write permission.

Path Parameters

idstring (uuid)required

The ID of the site to update.

Body Parameters

dataobjectrequired

The fields to update.

Request
curl \
  -X PUT \
  "https://api.cascade.dev/sites/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "data": {
    "name": "string",
    "slug": "string",
    "baseUrl": "https://example.com",
    "brandSettings": {
      "logoKey": "string",
      "iconKey": "string",
      "primaryColor": "string",
      "pageColor": "string",
      "contentColor": "string",
      "textColor": "string",
      "mutedColor": "string"
    },
    "metadata": "..."
  }
}'
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "string",
  "slug": "string",
  "baseUrl": "string",
  "brandSettings": {
    "primaryColor": "string",
    "pageColor": "string",
    "contentColor": "string",
    "textColor": "string",
    "mutedColor": "string",
    "logoUrl": "https://example.com",
    "iconUrl": "https://example.com"
  },
  "metadata": "...",
  "createdAt": "2025-01-15T09:30:00Z",
  "updatedAt": "2025-01-15T09:30:00Z"
}

DELETE /sites/{id}

Delete a site. It is marked for deletion straight away and its records are cleared out in the background, so the site keeps showing up briefly. You cannot delete an organization's last site. Triggers the site.deleted webhook.

Requires the settings:write permission.

Path Parameters

idstring (uuid)required

The ID of the site to delete.

Request
curl \
  -X DELETE \
  "https://api.cascade.dev/sites/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY"
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "string",
  "slug": "string",
  "baseUrl": "string",
  "brandSettings": {
    "primaryColor": "string",
    "pageColor": "string",
    "contentColor": "string",
    "textColor": "string",
    "mutedColor": "string",
    "logoUrl": "https://example.com",
    "iconUrl": "https://example.com"
  },
  "metadata": "...",
  "createdAt": "2025-01-15T09:30:00Z",
  "updatedAt": "2025-01-15T09:30:00Z"
}

GET /sites/{id}/widget-theme

Get how the storefront widgets look on one site: every property with the defaults filled in, the subset this site has actually changed, and the URL the widgets load the stylesheet from.

Requires the settings:read permission.

Path Parameters

idstring (uuid)required

The ID of the site.

Request
curl \
  "https://api.cascade.dev/sites/550e8400-e29b-41d4-a716-446655440000/widget-theme" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY"
Response
{
  "siteId": "550e8400-e29b-41d4-a716-446655440000",
  "theme": {
    "fontFamily": "string",
    "text": "string",
    "mutedText": "string",
    "surface": "string",
    "surfaceMuted": "string",
    "border": "string",
    "accent": "string",
    "accentText": "string",
    "star": "string",
    "danger": "string",
    "radius": "string",
    "customCss": "string"
  },
  "overrides": {
    "fontFamily": "string",
    "text": "string",
    "mutedText": "string",
    "surface": "string",
    "surfaceMuted": "string",
    "border": "string",
    "accent": "string",
    "accentText": "string",
    "star": "string",
    "danger": "string",
    "radius": "string",
    "customCss": "string"
  },
  "stylesheetUrl": "string",
  "notes": ["string"]
}

PATCH /sites/{id}/widget-theme

Change how the widgets look on one site. Only the properties you send are changed. Custom CSS is sanitized before it is stored: at-rules other than @media, @supports and @container are dropped, url() may only carry a data: URI, and every selector is scoped to the widget root so it cannot reach the rest of the page. Saving custom CSS also records a version you can restore.

Requires the settings:write permission.

Path Parameters

idstring (uuid)required

The ID of the site.

Body Parameters

dataobjectrequired

The properties to change. Anything you leave out keeps its current value, and setting a property to its default clears the override.

Request
curl \
  -X PATCH \
  "https://api.cascade.dev/sites/550e8400-e29b-41d4-a716-446655440000/widget-theme" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "data": {
    "fontFamily": "string",
    "text": "string",
    "mutedText": "string",
    "surface": "string",
    "surfaceMuted": "string",
    "border": "string",
    "accent": "string",
    "accentText": "string",
    "star": "string",
    "danger": "string",
    "radius": "string",
    "customCss": "string"
  }
}'
Response
{
  "siteId": "550e8400-e29b-41d4-a716-446655440000",
  "theme": {
    "fontFamily": "string",
    "text": "string",
    "mutedText": "string",
    "surface": "string",
    "surfaceMuted": "string",
    "border": "string",
    "accent": "string",
    "accentText": "string",
    "star": "string",
    "danger": "string",
    "radius": "string",
    "customCss": "string"
  },
  "overrides": {
    "fontFamily": "string",
    "text": "string",
    "mutedText": "string",
    "surface": "string",
    "surfaceMuted": "string",
    "border": "string",
    "accent": "string",
    "accentText": "string",
    "star": "string",
    "danger": "string",
    "radius": "string",
    "customCss": "string"
  },
  "stylesheetUrl": "string",
  "notes": ["string"]
}

POST /sites/{id}/widget-theme/copy

Copy another site's widget appearance onto this one, custom CSS included. It is a copy, not a link: the two drift apart as soon as either is edited again.

Requires the settings:write permission.

Path Parameters

idstring (uuid)required

The ID of the site.

Body Parameters

dataobjectrequired
Request
curl \
  -X POST \
  "https://api.cascade.dev/sites/550e8400-e29b-41d4-a716-446655440000/widget-theme/copy" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "data": {
    "fromSiteId": "550e8400-e29b-41d4-a716-446655440000"
  }
}'
Response
{
  "siteId": "550e8400-e29b-41d4-a716-446655440000",
  "theme": {
    "fontFamily": "string",
    "text": "string",
    "mutedText": "string",
    "surface": "string",
    "surfaceMuted": "string",
    "border": "string",
    "accent": "string",
    "accentText": "string",
    "star": "string",
    "danger": "string",
    "radius": "string",
    "customCss": "string"
  },
  "overrides": {
    "fontFamily": "string",
    "text": "string",
    "mutedText": "string",
    "surface": "string",
    "surfaceMuted": "string",
    "border": "string",
    "accent": "string",
    "accentText": "string",
    "star": "string",
    "danger": "string",
    "radius": "string",
    "customCss": "string"
  },
  "stylesheetUrl": "string",
  "notes": ["string"]
}

GET /sites/{id}/widget-theme/revisions

List the saved versions of this site's custom CSS, newest first. A version is recorded every time the CSS changes, whoever or whatever changed it.

Requires the settings:read permission.

Path Parameters

idstring (uuid)required

The ID of the site.

Request
curl \
  "https://api.cascade.dev/sites/550e8400-e29b-41d4-a716-446655440000/widget-theme/revisions" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY"
Response
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "customCss": "string",
      "source": "manual",
      "prompt": "string",
      "actorLabel": "string",
      "createdAt": "2025-01-15T09:30:00Z"
    }
  ]
}

POST /sites/{id}/widget-theme/revisions/{revisionId}/restore

Put a saved version of the custom CSS back. The restore is itself recorded as a version, so nothing is lost by undoing an undo.

Requires the settings:write permission.

Path Parameters

idstring (uuid)required

The ID of the site.

revisionIdstring (uuid)required

The ID of the version to restore.

Request
curl \
  -X POST \
  "https://api.cascade.dev/sites/550e8400-e29b-41d4-a716-446655440000/widget-theme/revisions/550e8400-e29b-41d4-a716-446655440000/restore" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY"
Response
{
  "siteId": "550e8400-e29b-41d4-a716-446655440000",
  "theme": {
    "fontFamily": "string",
    "text": "string",
    "mutedText": "string",
    "surface": "string",
    "surfaceMuted": "string",
    "border": "string",
    "accent": "string",
    "accentText": "string",
    "star": "string",
    "danger": "string",
    "radius": "string",
    "customCss": "string"
  },
  "overrides": {
    "fontFamily": "string",
    "text": "string",
    "mutedText": "string",
    "surface": "string",
    "surfaceMuted": "string",
    "border": "string",
    "accent": "string",
    "accentText": "string",
    "star": "string",
    "danger": "string",
    "radius": "string",
    "customCss": "string"
  },
  "stylesheetUrl": "string",
  "notes": ["string"]
}

POST /sites/{id}/widget-theme/suggest-css

Ask a model to write custom CSS for these widgets from a description. Nothing is saved: what comes back is already sanitized and scoped, so it is exactly what would be served, and you store it by sending it to PATCH /sites/{id}/widget-theme. Limited to 20 requests per organization, refilling at one a minute.

Requires the settings:write permission.

Costs 5 rate limit tokens instead of the usual one. See Rate limits.

Path Parameters

idstring (uuid)required

The ID of the site.

Body Parameters

dataobjectrequired
Request
curl \
  -X POST \
  "https://api.cascade.dev/sites/550e8400-e29b-41d4-a716-446655440000/widget-theme/suggest-css" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "data": {
    "prompt": "string"
  }
}'
Response
{
  "css": "string",
  "summary": "string",
  "notes": ["string"]
}