Workspace API

Site

Site endpoints of the Zanfia Workspace API, with schemas and code samples.

9 min readLast updated Sep 10, 2026

Your workspace's public site (Site → Settings): GET /site/settings returns the whole platformSettings document plus the client-communication base URL; each PATCH /site/settings/{slice} writes ONE atomic slice (general, theme, branding, main-page, privacy, portal, communication, access-policy) through the same use cases the dashboard uses, so omitted fields are never clobbered. POST /site/activate publishes/unpublishes the site. The slug and custom domains are heavier (they touch Stripe, Firebase Auth and Vercel): PATCH /site/slug, PUT /site/domains, then POST /site/domains/verify for the live DNS/TLS state. The storefront layout is a whole-config GET/PUT. Legal documents (terms + privacy policy) use the dashboard's write/link modes: write stores Markdown served at /documents/{slug}, link points at an external URL. Errors: 400 validation-failed / restricted-domain / no-domains-configured, 403 feature-not-available / unauthorized-domain, 404 main-page-not-found, 409 main-page-not-published / slug-taken / domain-taken, 503 not-configured (custom-domain routes on a deployment without Vercel access). All routes require a Authorization: Bearer header — see Authentication.

Get site settings

GET/site/settings

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Response Body

application/json

application/json

curl -X GET "https://example.com/site/settings"
{  "settings": {    "active": true,    "showPageTitle": true,    "pageTitle": "string",    "pageDescription": "string",    "slug": "string",    "domains": [      "string"    ],    "logoUrl": "string",    "logoDarkUrl": "string",    "platformFaviconUrl": "string",    "logo": {      "url": "string",      "mediaId": "string"    },    "logoDark": {      "url": "string",      "mediaId": "string"    },    "platformFavicon": {      "url": "string",      "mediaId": "string"    },    "theme": null,    "grayScale": null,    "radius": null,    "styleVariant": "solid",    "hideZanfiaBranding": true,    "mainPage": "/",    "mainPageId": "string",    "mainPageCommunityId": "string",    "cookieConsentEnabled": true,    "customColors": {      "light": {        "accent": "string",        "gray": "string",        "background": "string"      },      "dark": {        "accent": "string",        "gray": "string",        "background": "string"      }    },    "customCheckoutColors": {      "light": {        "checkoutLeftBackground": "string",        "checkoutRightBackground": "string",        "checkoutLeftTextColor": "string",        "checkoutLeftPriceColor": "string",        "accent": "string"      },      "dark": {        "checkoutLeftBackground": "string",        "checkoutRightBackground": "string",        "checkoutLeftTextColor": "string",        "checkoutLeftPriceColor": "string",        "accent": "string"      }    },    "customCheckoutTheme": {      "theme": "tomato",      "grayScale": "auto",      "radius": "none",      "styleVariant": "solid",      "customColors": {        "light": {          "accent": "string",          "gray": "string",          "background": "string"        },        "dark": {          "accent": "string",          "gray": "string",          "background": "string"        }      }    },    "selectedTheme": "light",    "language": "pl",    "portalCustomization": {      "libraryWidth": "full",      "libraryLayout": "grid",      "mobileLibraryLayout": "grid",      "libraryOrder": "newest",      "libraryCustomOrder": [        "string"      ],      "libraryGroupByType": true,      "defaultView": "library",      "messagesEnabled": true,      "clientMessagesEnabled": true    },    "customerAccessPolicy": {      "activeDeviceLimit": 0,      "replacementStrategy": "adaptive",      "version": "string"    },    "typography": {      "headingFamily": "string",      "bodyFamily": "string"    },    "themeFromBrand": true  },  "communication": {    "baseUrl": {      "type": "app"    }  }}
{  "error": "string",  "message": "string"}

Update general site settings

PATCH/site/settings/general

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

PATCH /site/settings/general — every field optional; an omitted field keeps its stored value (the shared use case leaves undefined slots untouched).

Response Body

application/json

application/json

curl -X PATCH "https://example.com/site/settings/general" \  -H "Content-Type: application/json" \  -d '{}'
{  "status": "ok"}
{  "error": "string",  "message": "string"}

Update site theme

PATCH/site/settings/theme

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X PATCH "https://example.com/site/settings/theme" \  -H "Content-Type: application/json" \  -d '{}'
{  "status": "ok"}
{  "error": "string",  "message": "string"}

Update site branding

PATCH/site/settings/branding

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X PATCH "https://example.com/site/settings/branding" \  -H "Content-Type: application/json" \  -d '{}'
{  "status": "ok"}
{  "error": "string",  "message": "string"}

Set the storefront root page

PATCH/site/settings/main-page

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Sets the storefront root: mainPage (sales vs dashboard) + mainPageId (the custom Page rendered at root, or null for the product storefront). When a non-null mainPageId is sent the use case verifies the page is Published.

Response Body

application/json

application/json

curl -X PATCH "https://example.com/site/settings/main-page" \  -H "Content-Type: application/json" \  -d '{}'
{  "status": "ok"}
{  "error": "string",  "message": "string"}
PATCH/site/settings/privacy

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X PATCH "https://example.com/site/settings/privacy" \  -H "Content-Type: application/json" \  -d '{}'
{  "status": "ok"}
{  "error": "string",  "message": "string"}

Update client-area customization

PATCH/site/settings/portal

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X PATCH "https://example.com/site/settings/portal" \  -H "Content-Type: application/json" \  -d '{}'
{  "status": "ok"}
{  "error": "string",  "message": "string"}

Update client communication base URL

PATCH/site/settings/communication

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Workspace-level client communication settings (workspaces/{wid}. clientsCommunicationSettings) — a sibling of platformSettings, not part of it. Holds the base URL used to build the links sent to customers.

Response Body

application/json

application/json

curl -X PATCH "https://example.com/site/settings/communication" \  -H "Content-Type: application/json" \  -d '{    "baseUrl": {      "type": "app"    }  }'
{  "status": "ok"}
{  "error": "string",  "message": "string"}

Update the customer device policy

PATCH/site/settings/access-policy

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X PATCH "https://example.com/site/settings/access-policy" \  -H "Content-Type: application/json" \  -d '{    "customerAccessPolicy": {      "activeDeviceLimit": 0    }  }'
{  "status": "ok"}
{  "error": "string",  "message": "string"}

Publish or unpublish the site

POST/site/activate

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Sets the platform "published/live" flag (platformSettings.active). A dedicated atomic endpoint: activation used to be forced on every legacy settings save; onboarding completion now sets it explicitly as its final step.

Response Body

application/json

application/json

curl -X POST "https://example.com/site/activate" \  -H "Content-Type: application/json" \  -d '{}'
{  "status": "ok"}
{  "error": "string",  "message": "string"}

Change the site slug

PATCH/site/slug

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Heavy slice — slug carries Stripe/Firebase/Vercel + cache/routing side effects.

Response Body

application/json

application/json

curl -X PATCH "https://example.com/site/slug" \  -H "Content-Type: application/json" \  -d '{}'
{  "status": "ok"}
{  "error": "string",  "message": "string"}

Replace the custom domains

PUT/site/domains

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Heavy slice — custom domains carry Stripe/Firebase/Vercel + cache side effects.

Response Body

application/json

application/json

curl -X PUT "https://example.com/site/domains" \  -H "Content-Type: application/json" \  -d '{}'
{  "status": "ok"}
{  "error": "string",  "message": "string"}

Verify custom domains

POST/site/domains/verify

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X POST "https://example.com/site/domains/verify" \  -H "Content-Type: application/json" \  -d '{    "domains": [      "string"    ]  }'
{  "results": [    {      "domain": "string",      "status": "verified",      "ssl": {        "state": "active",        "issuer": "string",        "validTo": "string"      }    }  ]}
{  "error": "string",  "message": "string"}

Get the storefront layout

GET/site/storefront

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Response Body

application/json

application/json

curl -X GET "https://example.com/site/storefront"
{  "sections": [    {      "id": "string",      "title": "string",      "description": "string",      "layout": "grid",      "mode": "manual",      "productIds": [        "string"      ],      "rule": {        "type": "allPublic",        "productType": "course",        "tag": "string"      },      "sort": "newest"    }  ],  "layout": "grid",  "columns": 0,  "preset": "platform",  "mode": "light",  "overrides": {    "accentColor": "string",    "colors": {      "light": {        "paper": "string",        "card": "string",        "ink": "string",        "accent": "string"      },      "dark": {        "paper": "string",        "card": "string",        "ink": "string",        "accent": "string"      }    },    "fontDisplay": "platform",    "fontBody": "platform",    "cardRadius": 0,    "imageRatio": "default",    "showBadge": true,    "showPrices": true,    "showSocialProof": true,    "descriptionLines": 0  },  "looseProductOrder": [    "string"  ],  "heading": "string",  "subheading": "string",  "footer": {    "showLegalLinks": true,    "contact": {      "businessName": "string",      "address": "string",      "email": "string",      "phone": "string",      "extraInfo": "string"    },    "socialLinks": [      {        "network": "facebook",        "url": "string"      }    ],    "customLinks": [      {        "id": "string",        "label": "string",        "url": "string"      }    ],    "copyrightText": "string"  }}
{  "error": "string",  "message": "string"}

Replace the storefront layout

PUT/site/storefront

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Full-replace of the storefront config (the manager holds the whole state).

Response Body

application/json

application/json

curl -X PUT "https://example.com/site/storefront" \  -H "Content-Type: application/json" \  -d '{    "sections": [      {        "id": "string",        "title": "string",        "layout": "grid",        "mode": "manual"      }    ]  }'
{  "sections": [    {      "id": "string",      "title": "string",      "description": "string",      "layout": "grid",      "mode": "manual",      "productIds": [        "string"      ],      "rule": {        "type": "allPublic",        "productType": "course",        "tag": "string"      },      "sort": "newest"    }  ],  "layout": "grid",  "columns": 0,  "preset": "platform",  "mode": "light",  "overrides": {    "accentColor": "string",    "colors": {      "light": {        "paper": "string",        "card": "string",        "ink": "string",        "accent": "string"      },      "dark": {        "paper": "string",        "card": "string",        "ink": "string",        "accent": "string"      }    },    "fontDisplay": "platform",    "fontBody": "platform",    "cardRadius": 0,    "imageRatio": "default",    "showBadge": true,    "showPrices": true,    "showSocialProof": true,    "descriptionLines": 0  },  "looseProductOrder": [    "string"  ],  "heading": "string",  "subheading": "string",  "footer": {    "showLegalLinks": true,    "contact": {      "businessName": "string",      "address": "string",      "email": "string",      "phone": "string",      "extraInfo": "string"    },    "socialLinks": [      {        "network": "facebook",        "url": "string"      }    ],    "customLinks": [      {        "id": "string",        "label": "string",        "url": "string"      }    ],    "copyrightText": "string"  }}
{  "error": "string",  "message": "string"}
GET/site/legal-documents

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Query Parameters

language?"pl"
Default"pl"

Value in

  • "pl"

Response Body

application/json

application/json

curl -X GET "https://example.com/site/legal-documents"
{  "language": "pl",  "termsContent": "string",  "termsUrl": "string",  "termsSlug": "string",  "privacyPolicyContent": "string",  "privacyPolicyUrl": "string",  "privacyPolicySlug": "string"}
{  "error": "string",  "message": "string"}
PATCH/site/legal-documents

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

PATCH /site/legal-documents — patch one or both documents.

Response Body

application/json

application/json

curl -X PATCH "https://example.com/site/legal-documents" \  -H "Content-Type: application/json" \  -d '{}'
{  "language": "pl",  "termsContent": "string",  "termsUrl": "string",  "termsSlug": "string",  "privacyPolicyContent": "string",  "privacyPolicyUrl": "string",  "privacyPolicySlug": "string"}
{  "error": "string",  "message": "string"}

Was this article helpful?

Related articles

Spotted something off? Tell us at support@zanfia.com.