DevelopersAPI reference

Website API

REST endpoints for website in SKUFlow: 25 operations with parameters, request and response fields, permissions and curl examples.

Base URL: https://app.skuflow.ai/api. Every call needs Authorization: Bearer skf_… (Authentication); {organizationId} ($ORGANIZATION_ID in the examples) is your business's id.

OperationEndpointRisk
The business's websiteGET /organizations/{organizationId}/websiteread
Build the websitePOST /organizations/{organizationId}/websitewrite
Change the website's settingsPATCH /organizations/{organizationId}/websitewrite
Delete the websiteDELETE /organizations/{organizationId}/websitesensitive
Write a fresh draftPOST /organizations/{organizationId}/website/regeneratesensitive
Apply a style from the galleryPOST /organizations/{organizationId}/website/stylewrite
Publish the websitePOST /organizations/{organizationId}/website/publishsensitive
Take the website downPOST /organizations/{organizationId}/website/unpublishsensitive
Preview the draftGET /organizations/{organizationId}/website/previewread
Website visitors and requestsGET /organizations/{organizationId}/website/statsread
Upload a website imagePOST /organizations/{organizationId}/website/image-upload-urlwrite
The website's image libraryGET /organizations/{organizationId}/website/mediaread
Add an uploaded image to the libraryPOST /organizations/{organizationId}/website/media/uploadswrite
Search free stock photosGET /organizations/{organizationId}/website/stock-photosread
Use a stock photoPOST /organizations/{organizationId}/website/media/stockwrite
Remove an image from the libraryDELETE /organizations/{organizationId}/website/media/{mediaId}sensitive
Add a pagePOST /organizations/{organizationId}/website/pageswrite
Edit a pagePATCH /organizations/{organizationId}/website/pages/{pageId}write
Delete a pageDELETE /organizations/{organizationId}/website/pages/{pageId}sensitive
Reorder the pagesPOST /organizations/{organizationId}/website/pages/orderwrite
Connect a custom domainPOST /organizations/{organizationId}/website/domainswrite
Check a domain's DNS nowPOST /organizations/{organizationId}/website/domains/{domainId}/verifywrite
Make a domain the main addressPOST /organizations/{organizationId}/website/domains/{domainId}/primarywrite
Disconnect a domainDELETE /organizations/{organizationId}/website/domains/{domainId}sensitive
Add an image to the website library (content in the request)POST /organizations/{organizationId}/website/media/contentwrite

The business's website

GET /organizations/{organizationId}/website

The website with its draft pages (sections included), theme, business details, SEO, publish state and custom domains; null before one is made (POST /website). Read-only.

Permissionwebsite.read (Owner, Admin, Staff)
Riskread, OAuth scope skuflow.read. Read: reads only.
MCP toolwebsite_get (toolset marketing)

Example

curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
idstring
subdomainstring
statusenumOne of DRAFT, PUBLISHED, UNPUBLISHED.
themeobject
theme.primaryColorstring
theme.accentColorstring
theme.fontenumOne of modern, classic, friendly, bold, elegant, geometric.
theme.radiusenumOne of square, soft, round.
theme.headerStyleenumOne of light, dark, brand.
theme.stylestringUp to 40 characters.
profileobject
profile.taglinestringUp to 160 characters.
profile.phonestringUp to 40 characters.
profile.emailempty string or string (email)
profile.addressstringUp to 300 characters.
profile.hoursobject
profile.hoursNotestringUp to 200 characters.
profile.licenseTextstringUp to 200 characters.
profile.serviceAreaTextstringUp to 600 characters.
profile.socialobject
profile.social.facebookempty string or string (uri)
profile.social.instagramempty string or string (uri)
profile.social.googleempty string or string (uri)
profile.social.yelpempty string or string (uri)
profile.social.nextdoorempty string or string (uri)
profile.logoUrlstringUp to 2000 characters.
profile.headerBrandenumOne of logoAndName, logo, name.
profile.logoSizeenumOne of small, medium, large.
profile.siteNamestringUp to 120 characters.
profile.privacyUrlempty string or string (uri)
profile.termsUrlempty string or string (uri)
profile.footerobject
profile.footer.showTaglineboolean
profile.footer.showContactboolean
profile.footer.showHoursboolean
profile.footer.showSocialboolean
profile.footer.showPoweredByboolean
profile.footer.copyrightstringUp to 200 characters.
seoTitlestring or null
seoDescriptionstring or null
publishedAtstring (date-time) or null
generatedBystring or nullAI (written by Claude) or TEMPLATE.
tradestring or nullThe trade template it was built from (e.g. screen-printing, embroidery); null when none.
defaultUrlstring or nullhttps://{subdomain}.{sites domain}, when one is configured.
pathstring/sites/{subdomain} on the app: always works.
hasUnpublishedChangesboolean
pagesarray of object
pages[].idstring
pages[].slugstringThe page address; "" is the home page.
pages[].titlestring
pages[].showInNavboolean
pages[].sortOrderinteger
pages[].seoTitlestring or null
pages[].seoDescriptionstring or null
pages[].sectionsarray of object
pages[].sections[].idstring
pages[].sections[].typestringhero, trust, services, about, testimonials, booking (the request form), serviceArea, faq, cta, contact, gallery or text.
pages[].sections[].hiddenboolean
pages[].sections[].propsobjectThe section's fields; their schema per type is in.
pages[].updatedAtstring (date-time)
domainsarray of object
domains[].idstring
domains[].hostnamestring
domains[].statusenumOne of PENDING, ACTIVE, FAILED.
domains[].verificationTokenstringThe value of the TXT record at recordName.
domains[].recordNamestring
domains[].cnameTargetstring or nullWhere the domain's CNAME (or A records) must point.
domains[].apexbooleanA bare domain (example.com): A records instead of a CNAME.
domains[].recordsarray of objectEvery DNS record to add: the ownership TXT, then the CNAME (or A records).
domains[].records[].typeenumOne of TXT, CNAME, A.
domains[].records[].namestringRelative to the domain, as DNS providers ask: "@", "www", "_skuflow.www".
domains[].records[].fullNamestring
domains[].records[].valuestring
domains[].records[].purposeenumOne of verify, route.
domains[].verifiedAtstring (date-time) or null
domains[].lastCheckedAtstring (date-time) or null
domains[].lastErrorstring or null
domains[].isPrimaryboolean
domains[].createdAtstring (date-time)
createdAtstring (date-time)
updatedAtstring (date-time)

Build the website

POST /organizations/{organizationId}/website

Makes the business's website as a DRAFT (nobody outside sees it until POST /website/publish): Claude writes the copy from the business's own records (what it does, its place, its trade template) and invents no reviews or claims; without a model configured a template is used (generatedBy). Pages: home, services, plans (when there are plans), about, book, contact. 409 when one exists.

Permissionwebsite.manage (Owner, Admin)
Riskwrite, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolwebsite_create (toolset marketing)
PlanWebsite builder: the Grow plan and up.

Request body

FieldTypeRequiredDescription
subdomainstringNoThe site's address under the sites domain: lower-case letters, numbers and hyphens. Up to 40 characters.
tradestring or nullNoThe trade template: its style, curated banner and about photos, and copy for its customers. One of: screen-printing, embroidery, promotional-products, print-on-demand, signs-and-graphics, other. Up to 40 characters.
stylestring or nullNoA style from the gallery instead of the trade's own (POST /website/style lists them). Up to 40 characters.

Example

curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"subdomain":"string","trade":"string","style":"string"}'

Response

201: the answer's fields
FieldTypeDescription
idstring
subdomainstring
statusenumOne of DRAFT, PUBLISHED, UNPUBLISHED.
themeobject
theme.primaryColorstring
theme.accentColorstring
theme.fontenumOne of modern, classic, friendly, bold, elegant, geometric.
theme.radiusenumOne of square, soft, round.
theme.headerStyleenumOne of light, dark, brand.
theme.stylestringUp to 40 characters.
profileobject
profile.taglinestringUp to 160 characters.
profile.phonestringUp to 40 characters.
profile.emailempty string or string (email)
profile.addressstringUp to 300 characters.
profile.hoursobject
profile.hoursNotestringUp to 200 characters.
profile.licenseTextstringUp to 200 characters.
profile.serviceAreaTextstringUp to 600 characters.
profile.socialobject
profile.social.facebookempty string or string (uri)
profile.social.instagramempty string or string (uri)
profile.social.googleempty string or string (uri)
profile.social.yelpempty string or string (uri)
profile.social.nextdoorempty string or string (uri)
profile.logoUrlstringUp to 2000 characters.
profile.headerBrandenumOne of logoAndName, logo, name.
profile.logoSizeenumOne of small, medium, large.
profile.siteNamestringUp to 120 characters.
profile.privacyUrlempty string or string (uri)
profile.termsUrlempty string or string (uri)
profile.footerobject
profile.footer.showTaglineboolean
profile.footer.showContactboolean
profile.footer.showHoursboolean
profile.footer.showSocialboolean
profile.footer.showPoweredByboolean
profile.footer.copyrightstringUp to 200 characters.
seoTitlestring or null
seoDescriptionstring or null
publishedAtstring (date-time) or null
generatedBystring or nullAI (written by Claude) or TEMPLATE.
tradestring or nullThe trade template it was built from (e.g. screen-printing, embroidery); null when none.
defaultUrlstring or nullhttps://{subdomain}.{sites domain}, when one is configured.
pathstring/sites/{subdomain} on the app: always works.
hasUnpublishedChangesboolean
pagesarray of object
pages[].idstring
pages[].slugstringThe page address; "" is the home page.
pages[].titlestring
pages[].showInNavboolean
pages[].sortOrderinteger
pages[].seoTitlestring or null
pages[].seoDescriptionstring or null
pages[].sectionsarray of object
pages[].sections[].idstring
pages[].sections[].typestringhero, trust, services, about, testimonials, booking (the request form), serviceArea, faq, cta, contact, gallery or text.
pages[].sections[].hiddenboolean
pages[].sections[].propsobjectThe section's fields; their schema per type is in.
pages[].updatedAtstring (date-time)
domainsarray of object
domains[].idstring
domains[].hostnamestring
domains[].statusenumOne of PENDING, ACTIVE, FAILED.
domains[].verificationTokenstringThe value of the TXT record at recordName.
domains[].recordNamestring
domains[].cnameTargetstring or nullWhere the domain's CNAME (or A records) must point.
domains[].apexbooleanA bare domain (example.com): A records instead of a CNAME.
domains[].recordsarray of objectEvery DNS record to add: the ownership TXT, then the CNAME (or A records).
domains[].records[].typeenumOne of TXT, CNAME, A.
domains[].records[].namestringRelative to the domain, as DNS providers ask: "@", "www", "_skuflow.www".
domains[].records[].fullNamestring
domains[].records[].valuestring
domains[].records[].purposeenumOne of verify, route.
domains[].verifiedAtstring (date-time) or null
domains[].lastCheckedAtstring (date-time) or null
domains[].lastErrorstring or null
domains[].isPrimaryboolean
domains[].createdAtstring (date-time)
createdAtstring (date-time)
updatedAtstring (date-time)

Change the website's settings

PATCH /organizations/{organizationId}/website

Changes the fields sent in the draft: subdomain (409 when taken; a published site moves at once), theme, business profile (merged), SEO. Publish to show the changes on the live site (the subdomain change applies immediately).

Permissionwebsite.manage (Owner, Admin)
Riskwrite, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolwebsite_update (toolset marketing)
PlanWebsite builder: the Grow plan and up.

Request body

FieldTypeRequiredDescription
subdomainstringNoThe site's address under the sites domain: lower-case letters, numbers and hyphens. Up to 40 characters.
tradestring or nullNoThe trade template: steers photo suggestions and the next fresh draft. Up to 40 characters.
themeobjectNo
theme.primaryColorstringNo
theme.accentColorstringNo
theme.fontenumNoOne of modern, classic, friendly, bold, elegant, geometric.
theme.radiusenumNoOne of square, soft, round.
theme.headerStyleenumNoOne of light, dark, brand.
theme.stylestringNoUp to 40 characters.
profileobjectNoMerged into the business details: send only what changes (hours and links per day / network).
profile.taglinestringNoUp to 160 characters.
profile.phonestringNoUp to 40 characters.
profile.emailempty string or string (email)No
profile.addressstringNoUp to 300 characters.
profile.hoursobjectNo
profile.hoursNotestringNoUp to 200 characters.
profile.licenseTextstringNoUp to 200 characters.
profile.serviceAreaTextstringNoUp to 600 characters.
profile.socialobjectNo
profile.social.facebookempty string or string (uri)No
profile.social.instagramempty string or string (uri)No
profile.social.googleempty string or string (uri)No
profile.social.yelpempty string or string (uri)No
profile.social.nextdoorempty string or string (uri)No
profile.logoUrlstringNoUp to 2000 characters.
profile.headerBrandenumNoOne of logoAndName, logo, name.
profile.logoSizeenumNoOne of small, medium, large.
profile.siteNamestringNoUp to 120 characters.
profile.privacyUrlempty string or string (uri)No
profile.termsUrlempty string or string (uri)No
profile.footerobjectNo
profile.footer.showTaglinebooleanNo
profile.footer.showContactbooleanNo
profile.footer.showHoursbooleanNo
profile.footer.showSocialbooleanNo
profile.footer.showPoweredBybooleanNo
profile.footer.copyrightstringNoUp to 200 characters.
seoTitlestring or nullNoUp to 70 characters.
seoDescriptionstring or nullNoUp to 170 characters.

Example

curl -X PATCH "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"subdomain":"string","trade":"string","theme":{"primaryColor":"string","accentColor":"string","font":"modern"}}'

Response

200: the answer's fields
FieldTypeDescription
idstring
subdomainstring
statusenumOne of DRAFT, PUBLISHED, UNPUBLISHED.
themeobject
theme.primaryColorstring
theme.accentColorstring
theme.fontenumOne of modern, classic, friendly, bold, elegant, geometric.
theme.radiusenumOne of square, soft, round.
theme.headerStyleenumOne of light, dark, brand.
theme.stylestringUp to 40 characters.
profileobject
profile.taglinestringUp to 160 characters.
profile.phonestringUp to 40 characters.
profile.emailempty string or string (email)
profile.addressstringUp to 300 characters.
profile.hoursobject
profile.hoursNotestringUp to 200 characters.
profile.licenseTextstringUp to 200 characters.
profile.serviceAreaTextstringUp to 600 characters.
profile.socialobject
profile.social.facebookempty string or string (uri)
profile.social.instagramempty string or string (uri)
profile.social.googleempty string or string (uri)
profile.social.yelpempty string or string (uri)
profile.social.nextdoorempty string or string (uri)
profile.logoUrlstringUp to 2000 characters.
profile.headerBrandenumOne of logoAndName, logo, name.
profile.logoSizeenumOne of small, medium, large.
profile.siteNamestringUp to 120 characters.
profile.privacyUrlempty string or string (uri)
profile.termsUrlempty string or string (uri)
profile.footerobject
profile.footer.showTaglineboolean
profile.footer.showContactboolean
profile.footer.showHoursboolean
profile.footer.showSocialboolean
profile.footer.showPoweredByboolean
profile.footer.copyrightstringUp to 200 characters.
seoTitlestring or null
seoDescriptionstring or null
publishedAtstring (date-time) or null
generatedBystring or nullAI (written by Claude) or TEMPLATE.
tradestring or nullThe trade template it was built from (e.g. screen-printing, embroidery); null when none.
defaultUrlstring or nullhttps://{subdomain}.{sites domain}, when one is configured.
pathstring/sites/{subdomain} on the app: always works.
hasUnpublishedChangesboolean
pagesarray of object
pages[].idstring
pages[].slugstringThe page address; "" is the home page.
pages[].titlestring
pages[].showInNavboolean
pages[].sortOrderinteger
pages[].seoTitlestring or null
pages[].seoDescriptionstring or null
pages[].sectionsarray of object
pages[].sections[].idstring
pages[].sections[].typestringhero, trust, services, about, testimonials, booking (the request form), serviceArea, faq, cta, contact, gallery or text.
pages[].sections[].hiddenboolean
pages[].sections[].propsobjectThe section's fields; their schema per type is in.
pages[].updatedAtstring (date-time)
domainsarray of object
domains[].idstring
domains[].hostnamestring
domains[].statusenumOne of PENDING, ACTIVE, FAILED.
domains[].verificationTokenstringThe value of the TXT record at recordName.
domains[].recordNamestring
domains[].cnameTargetstring or nullWhere the domain's CNAME (or A records) must point.
domains[].apexbooleanA bare domain (example.com): A records instead of a CNAME.
domains[].recordsarray of objectEvery DNS record to add: the ownership TXT, then the CNAME (or A records).
domains[].records[].typeenumOne of TXT, CNAME, A.
domains[].records[].namestringRelative to the domain, as DNS providers ask: "@", "www", "_skuflow.www".
domains[].records[].fullNamestring
domains[].records[].valuestring
domains[].records[].purposeenumOne of verify, route.
domains[].verifiedAtstring (date-time) or null
domains[].lastCheckedAtstring (date-time) or null
domains[].lastErrorstring or null
domains[].isPrimaryboolean
domains[].createdAtstring (date-time)
createdAtstring (date-time)
updatedAtstring (date-time)

Delete the website

DELETE /organizations/{organizationId}/website

DESTRUCTIVE and permanent: deletes the website with every page, custom domain and visitor stat; a published site goes offline at once (its addresses answer 404). The image library stays, and POST /website can build a new one. confirm must equal the site's subdomain (400 otherwise). Emits website.deleted.

Permissionwebsite.manage (Owner, Admin)
Risksensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.
MCP toolwebsite_delete (toolset marketing)
ApprovalOver MCP, this tool always waits for your approval in SKUFlow. See Approvals.

Request body

FieldTypeRequiredDescription
confirmstringYesThe site's subdomain, typed by the user to confirm. Up to 60 characters.

Example

curl -X DELETE "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
oktrue

Write a fresh draft

POST /organizations/{organizationId}/website/regenerate

DESTRUCTIVE for the draft: replaces every draft page with a newly written set (theme, domains and filled-in business details stay). The published site is unchanged until published again.

Permissionwebsite.manage (Owner, Admin)
Risksensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.
MCP toolwebsite_regenerate (toolset marketing)
PlanWebsite builder: the Grow plan and up.
ApprovalOver MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in SKUFlow). See Approvals.

Example

curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/regenerate" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
idstring
subdomainstring
statusenumOne of DRAFT, PUBLISHED, UNPUBLISHED.
themeobject
theme.primaryColorstring
theme.accentColorstring
theme.fontenumOne of modern, classic, friendly, bold, elegant, geometric.
theme.radiusenumOne of square, soft, round.
theme.headerStyleenumOne of light, dark, brand.
theme.stylestringUp to 40 characters.
profileobject
profile.taglinestringUp to 160 characters.
profile.phonestringUp to 40 characters.
profile.emailempty string or string (email)
profile.addressstringUp to 300 characters.
profile.hoursobject
profile.hoursNotestringUp to 200 characters.
profile.licenseTextstringUp to 200 characters.
profile.serviceAreaTextstringUp to 600 characters.
profile.socialobject
profile.social.facebookempty string or string (uri)
profile.social.instagramempty string or string (uri)
profile.social.googleempty string or string (uri)
profile.social.yelpempty string or string (uri)
profile.social.nextdoorempty string or string (uri)
profile.logoUrlstringUp to 2000 characters.
profile.headerBrandenumOne of logoAndName, logo, name.
profile.logoSizeenumOne of small, medium, large.
profile.siteNamestringUp to 120 characters.
profile.privacyUrlempty string or string (uri)
profile.termsUrlempty string or string (uri)
profile.footerobject
profile.footer.showTaglineboolean
profile.footer.showContactboolean
profile.footer.showHoursboolean
profile.footer.showSocialboolean
profile.footer.showPoweredByboolean
profile.footer.copyrightstringUp to 200 characters.
seoTitlestring or null
seoDescriptionstring or null
publishedAtstring (date-time) or null
generatedBystring or nullAI (written by Claude) or TEMPLATE.
tradestring or nullThe trade template it was built from (e.g. screen-printing, embroidery); null when none.
defaultUrlstring or nullhttps://{subdomain}.{sites domain}, when one is configured.
pathstring/sites/{subdomain} on the app: always works.
hasUnpublishedChangesboolean
pagesarray of object
pages[].idstring
pages[].slugstringThe page address; "" is the home page.
pages[].titlestring
pages[].showInNavboolean
pages[].sortOrderinteger
pages[].seoTitlestring or null
pages[].seoDescriptionstring or null
pages[].sectionsarray of object
pages[].sections[].idstring
pages[].sections[].typestringhero, trust, services, about, testimonials, booking (the request form), serviceArea, faq, cta, contact, gallery or text.
pages[].sections[].hiddenboolean
pages[].sections[].propsobjectThe section's fields; their schema per type is in.
pages[].updatedAtstring (date-time)
domainsarray of object
domains[].idstring
domains[].hostnamestring
domains[].statusenumOne of PENDING, ACTIVE, FAILED.
domains[].verificationTokenstringThe value of the TXT record at recordName.
domains[].recordNamestring
domains[].cnameTargetstring or nullWhere the domain's CNAME (or A records) must point.
domains[].apexbooleanA bare domain (example.com): A records instead of a CNAME.
domains[].recordsarray of objectEvery DNS record to add: the ownership TXT, then the CNAME (or A records).
domains[].records[].typeenumOne of TXT, CNAME, A.
domains[].records[].namestringRelative to the domain, as DNS providers ask: "@", "www", "_skuflow.www".
domains[].records[].fullNamestring
domains[].records[].valuestring
domains[].records[].purposeenumOne of verify, route.
domains[].verifiedAtstring (date-time) or null
domains[].lastCheckedAtstring (date-time) or null
domains[].lastErrorstring or null
domains[].isPrimaryboolean
domains[].createdAtstring (date-time)
createdAtstring (date-time)
updatedAtstring (date-time)

Apply a style from the gallery

POST /organizations/{organizationId}/website/style

Changes the draft's look in one step: the theme (colours unless keepColors, type, corners, header) and the layout of every block on every page. Words and photos stay; the live site changes when published. Styles: clean, bold, classic, friendly, elegant, fresh, cool, warm.

Permissionwebsite.manage (Owner, Admin)
Riskwrite, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolwebsite_applyStyle (toolset marketing)
PlanWebsite builder: the Grow plan and up.

Request body

FieldTypeRequiredDescription
stylestringYesUp to 40 characters.
keepColorsbooleanNoKeep the business's own primary and accent colours.

Example

curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/style" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"style":"string"}'

Response

200: the answer's fields
FieldTypeDescription
idstring
subdomainstring
statusenumOne of DRAFT, PUBLISHED, UNPUBLISHED.
themeobject
theme.primaryColorstring
theme.accentColorstring
theme.fontenumOne of modern, classic, friendly, bold, elegant, geometric.
theme.radiusenumOne of square, soft, round.
theme.headerStyleenumOne of light, dark, brand.
theme.stylestringUp to 40 characters.
profileobject
profile.taglinestringUp to 160 characters.
profile.phonestringUp to 40 characters.
profile.emailempty string or string (email)
profile.addressstringUp to 300 characters.
profile.hoursobject
profile.hoursNotestringUp to 200 characters.
profile.licenseTextstringUp to 200 characters.
profile.serviceAreaTextstringUp to 600 characters.
profile.socialobject
profile.social.facebookempty string or string (uri)
profile.social.instagramempty string or string (uri)
profile.social.googleempty string or string (uri)
profile.social.yelpempty string or string (uri)
profile.social.nextdoorempty string or string (uri)
profile.logoUrlstringUp to 2000 characters.
profile.headerBrandenumOne of logoAndName, logo, name.
profile.logoSizeenumOne of small, medium, large.
profile.siteNamestringUp to 120 characters.
profile.privacyUrlempty string or string (uri)
profile.termsUrlempty string or string (uri)
profile.footerobject
profile.footer.showTaglineboolean
profile.footer.showContactboolean
profile.footer.showHoursboolean
profile.footer.showSocialboolean
profile.footer.showPoweredByboolean
profile.footer.copyrightstringUp to 200 characters.
seoTitlestring or null
seoDescriptionstring or null
publishedAtstring (date-time) or null
generatedBystring or nullAI (written by Claude) or TEMPLATE.
tradestring or nullThe trade template it was built from (e.g. screen-printing, embroidery); null when none.
defaultUrlstring or nullhttps://{subdomain}.{sites domain}, when one is configured.
pathstring/sites/{subdomain} on the app: always works.
hasUnpublishedChangesboolean
pagesarray of object
pages[].idstring
pages[].slugstringThe page address; "" is the home page.
pages[].titlestring
pages[].showInNavboolean
pages[].sortOrderinteger
pages[].seoTitlestring or null
pages[].seoDescriptionstring or null
pages[].sectionsarray of object
pages[].sections[].idstring
pages[].sections[].typestringhero, trust, services, about, testimonials, booking (the request form), serviceArea, faq, cta, contact, gallery or text.
pages[].sections[].hiddenboolean
pages[].sections[].propsobjectThe section's fields; their schema per type is in.
pages[].updatedAtstring (date-time)
domainsarray of object
domains[].idstring
domains[].hostnamestring
domains[].statusenumOne of PENDING, ACTIVE, FAILED.
domains[].verificationTokenstringThe value of the TXT record at recordName.
domains[].recordNamestring
domains[].cnameTargetstring or nullWhere the domain's CNAME (or A records) must point.
domains[].apexbooleanA bare domain (example.com): A records instead of a CNAME.
domains[].recordsarray of objectEvery DNS record to add: the ownership TXT, then the CNAME (or A records).
domains[].records[].typeenumOne of TXT, CNAME, A.
domains[].records[].namestringRelative to the domain, as DNS providers ask: "@", "www", "_skuflow.www".
domains[].records[].fullNamestring
domains[].records[].valuestring
domains[].records[].purposeenumOne of verify, route.
domains[].verifiedAtstring (date-time) or null
domains[].lastCheckedAtstring (date-time) or null
domains[].lastErrorstring or null
domains[].isPrimaryboolean
domains[].createdAtstring (date-time)
createdAtstring (date-time)
updatedAtstring (date-time)

Publish the website

POST /organizations/{organizationId}/website/publish

EXPOSES the draft to the public: freezes every page as it stands and serves it at the site's addresses (subdomain and active custom domains). Republishing replaces the live site. Emits website.published.

Permissionwebsite.manage (Owner, Admin)
Risksensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.
MCP toolwebsite_publish (toolset marketing)
PlanWebsite builder: the Grow plan and up.
ApprovalOver MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in SKUFlow). See Approvals.

Example

curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/publish" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
idstring
subdomainstring
statusenumOne of DRAFT, PUBLISHED, UNPUBLISHED.
themeobject
theme.primaryColorstring
theme.accentColorstring
theme.fontenumOne of modern, classic, friendly, bold, elegant, geometric.
theme.radiusenumOne of square, soft, round.
theme.headerStyleenumOne of light, dark, brand.
theme.stylestringUp to 40 characters.
profileobject
profile.taglinestringUp to 160 characters.
profile.phonestringUp to 40 characters.
profile.emailempty string or string (email)
profile.addressstringUp to 300 characters.
profile.hoursobject
profile.hoursNotestringUp to 200 characters.
profile.licenseTextstringUp to 200 characters.
profile.serviceAreaTextstringUp to 600 characters.
profile.socialobject
profile.social.facebookempty string or string (uri)
profile.social.instagramempty string or string (uri)
profile.social.googleempty string or string (uri)
profile.social.yelpempty string or string (uri)
profile.social.nextdoorempty string or string (uri)
profile.logoUrlstringUp to 2000 characters.
profile.headerBrandenumOne of logoAndName, logo, name.
profile.logoSizeenumOne of small, medium, large.
profile.siteNamestringUp to 120 characters.
profile.privacyUrlempty string or string (uri)
profile.termsUrlempty string or string (uri)
profile.footerobject
profile.footer.showTaglineboolean
profile.footer.showContactboolean
profile.footer.showHoursboolean
profile.footer.showSocialboolean
profile.footer.showPoweredByboolean
profile.footer.copyrightstringUp to 200 characters.
seoTitlestring or null
seoDescriptionstring or null
publishedAtstring (date-time) or null
generatedBystring or nullAI (written by Claude) or TEMPLATE.
tradestring or nullThe trade template it was built from (e.g. screen-printing, embroidery); null when none.
defaultUrlstring or nullhttps://{subdomain}.{sites domain}, when one is configured.
pathstring/sites/{subdomain} on the app: always works.
hasUnpublishedChangesboolean
pagesarray of object
pages[].idstring
pages[].slugstringThe page address; "" is the home page.
pages[].titlestring
pages[].showInNavboolean
pages[].sortOrderinteger
pages[].seoTitlestring or null
pages[].seoDescriptionstring or null
pages[].sectionsarray of object
pages[].sections[].idstring
pages[].sections[].typestringhero, trust, services, about, testimonials, booking (the request form), serviceArea, faq, cta, contact, gallery or text.
pages[].sections[].hiddenboolean
pages[].sections[].propsobjectThe section's fields; their schema per type is in.
pages[].updatedAtstring (date-time)
domainsarray of object
domains[].idstring
domains[].hostnamestring
domains[].statusenumOne of PENDING, ACTIVE, FAILED.
domains[].verificationTokenstringThe value of the TXT record at recordName.
domains[].recordNamestring
domains[].cnameTargetstring or nullWhere the domain's CNAME (or A records) must point.
domains[].apexbooleanA bare domain (example.com): A records instead of a CNAME.
domains[].recordsarray of objectEvery DNS record to add: the ownership TXT, then the CNAME (or A records).
domains[].records[].typeenumOne of TXT, CNAME, A.
domains[].records[].namestringRelative to the domain, as DNS providers ask: "@", "www", "_skuflow.www".
domains[].records[].fullNamestring
domains[].records[].valuestring
domains[].records[].purposeenumOne of verify, route.
domains[].verifiedAtstring (date-time) or null
domains[].lastCheckedAtstring (date-time) or null
domains[].lastErrorstring or null
domains[].isPrimaryboolean
domains[].createdAtstring (date-time)
createdAtstring (date-time)
updatedAtstring (date-time)

Take the website down

POST /organizations/{organizationId}/website/unpublish

The live site's addresses answer 404 until published again; the draft is kept. 409 when not published.

Permissionwebsite.manage (Owner, Admin)
Risksensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.
MCP toolwebsite_unpublish (toolset marketing)
ApprovalOver MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in SKUFlow). See Approvals.

Example

curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/unpublish" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
idstring
subdomainstring
statusenumOne of DRAFT, PUBLISHED, UNPUBLISHED.
themeobject
theme.primaryColorstring
theme.accentColorstring
theme.fontenumOne of modern, classic, friendly, bold, elegant, geometric.
theme.radiusenumOne of square, soft, round.
theme.headerStyleenumOne of light, dark, brand.
theme.stylestringUp to 40 characters.
profileobject
profile.taglinestringUp to 160 characters.
profile.phonestringUp to 40 characters.
profile.emailempty string or string (email)
profile.addressstringUp to 300 characters.
profile.hoursobject
profile.hoursNotestringUp to 200 characters.
profile.licenseTextstringUp to 200 characters.
profile.serviceAreaTextstringUp to 600 characters.
profile.socialobject
profile.social.facebookempty string or string (uri)
profile.social.instagramempty string or string (uri)
profile.social.googleempty string or string (uri)
profile.social.yelpempty string or string (uri)
profile.social.nextdoorempty string or string (uri)
profile.logoUrlstringUp to 2000 characters.
profile.headerBrandenumOne of logoAndName, logo, name.
profile.logoSizeenumOne of small, medium, large.
profile.siteNamestringUp to 120 characters.
profile.privacyUrlempty string or string (uri)
profile.termsUrlempty string or string (uri)
profile.footerobject
profile.footer.showTaglineboolean
profile.footer.showContactboolean
profile.footer.showHoursboolean
profile.footer.showSocialboolean
profile.footer.showPoweredByboolean
profile.footer.copyrightstringUp to 200 characters.
seoTitlestring or null
seoDescriptionstring or null
publishedAtstring (date-time) or null
generatedBystring or nullAI (written by Claude) or TEMPLATE.
tradestring or nullThe trade template it was built from (e.g. screen-printing, embroidery); null when none.
defaultUrlstring or nullhttps://{subdomain}.{sites domain}, when one is configured.
pathstring/sites/{subdomain} on the app: always works.
hasUnpublishedChangesboolean
pagesarray of object
pages[].idstring
pages[].slugstringThe page address; "" is the home page.
pages[].titlestring
pages[].showInNavboolean
pages[].sortOrderinteger
pages[].seoTitlestring or null
pages[].seoDescriptionstring or null
pages[].sectionsarray of object
pages[].sections[].idstring
pages[].sections[].typestringhero, trust, services, about, testimonials, booking (the request form), serviceArea, faq, cta, contact, gallery or text.
pages[].sections[].hiddenboolean
pages[].sections[].propsobjectThe section's fields; their schema per type is in.
pages[].updatedAtstring (date-time)
domainsarray of object
domains[].idstring
domains[].hostnamestring
domains[].statusenumOne of PENDING, ACTIVE, FAILED.
domains[].verificationTokenstringThe value of the TXT record at recordName.
domains[].recordNamestring
domains[].cnameTargetstring or nullWhere the domain's CNAME (or A records) must point.
domains[].apexbooleanA bare domain (example.com): A records instead of a CNAME.
domains[].recordsarray of objectEvery DNS record to add: the ownership TXT, then the CNAME (or A records).
domains[].records[].typeenumOne of TXT, CNAME, A.
domains[].records[].namestringRelative to the domain, as DNS providers ask: "@", "www", "_skuflow.www".
domains[].records[].fullNamestring
domains[].records[].valuestring
domains[].records[].purposeenumOne of verify, route.
domains[].verifiedAtstring (date-time) or null
domains[].lastCheckedAtstring (date-time) or null
domains[].lastErrorstring or null
domains[].isPrimaryboolean
domains[].createdAtstring (date-time)
createdAtstring (date-time)
updatedAtstring (date-time)

Preview the draft

GET /organizations/{organizationId}/website/preview

The draft site exactly as POST /website/publish would serve it, with the live request form and phone settings. Read-only.

Permissionwebsite.read (Owner, Admin, Staff)
Riskread, OAuth scope skuflow.read. Read: reads only.
MCP toolwebsite_preview (toolset marketing)

Example

curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/preview" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
subdomainstring
canonicalHoststring or null
publishedAtstring (date-time)
siteobject
site.themeobject
site.theme.primaryColorstring
site.theme.accentColorstring
site.theme.fontenumOne of modern, classic, friendly, bold, elegant, geometric.
site.theme.radiusenumOne of square, soft, round.
site.theme.headerStyleenumOne of light, dark, brand.
site.theme.stylestringUp to 40 characters.
site.profileobject
site.profile.taglinestringUp to 160 characters.
site.profile.phonestringUp to 40 characters.
site.profile.emailempty string or string (email)
site.profile.addressstringUp to 300 characters.
site.profile.hoursobject
site.profile.hoursNotestringUp to 200 characters.
site.profile.licenseTextstringUp to 200 characters.
site.profile.serviceAreaTextstringUp to 600 characters.
site.profile.socialobject
site.profile.logoUrlstringUp to 2000 characters.
site.profile.headerBrandenumOne of logoAndName, logo, name.
site.profile.logoSizeenumOne of small, medium, large.
site.profile.siteNamestringUp to 120 characters.
site.profile.privacyUrlempty string or string (uri)
site.profile.termsUrlempty string or string (uri)
site.profile.footerobject
site.seoTitlestring or null
site.seoDescriptionstring or null
site.pagesarray of object
site.pages[].slugstring
site.pages[].titlestring
site.pages[].showInNavboolean
site.pages[].seoTitlestring or null
site.pages[].seoDescriptionstring or null
site.pages[].sectionsarray of object
site.photoCreditsarray of objectCredits for the stock photos the site shows; the footer lists them.
site.photoCredits[].providerstring
site.photoCredits[].authorstring
site.photoCredits[].authorUrlstring
site.photoCredits[].sourceUrlstring
organizationSlugstringFor the request form: /api/public/book/{organizationSlug}.
businessNamestring
customerSignInbooleanCustomers can sign in at /c/{organizationSlug}: the header shows Customer login.
logostring or null
timezonestring
bookingobject
booking.enabledbooleanThe request form takes requests.
trackingNumbersarray of objectDynamic number insertion: tracking numbers by visitor source; the site's phone links show the matching one.
trackingNumbers[].phonestring
trackingNumbers[].isDefaultboolean
trackingNumbers[].utmSourcestring or null
trackingNumbers[].utmMediumstring or null
trackingNumbers[].campaignIdstring or null

Website visitors and requests

GET /organizations/{organizationId}/website/stats

Page views per day and the top pages over days (default 30), and online requests by channel (request page, widget, website). Read-only.

Permissionwebsite.read (Owner, Admin, Staff)
Riskread, OAuth scope skuflow.read. Read: reads only.
MCP toolwebsite_stats (toolset marketing)

Parameters

NameInTypeRequiredDescription
daysqueryintegerNo7–90.

Example

curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/stats" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
fromstring
tostring
viewsinteger
daysarray of object
days[].datestring
days[].viewsinteger
topPagesarray of object
topPages[].pathstring
topPages[].viewsinteger
requestsobject
requests.BOOKING_PAGEinteger
requests.WIDGETinteger
requests.WEBSITEinteger

Upload a website image

POST /organizations/{organizationId}/website/image-upload-url

Step 1 of adding an image to a section: returns a signed URL to PUT the file to (with the same Content-Type) and the url to put in the section (hero, about, gallery).

Permissionwebsite.manage (Owner, Admin)
Riskwrite, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolwebsite_createImageUploadUrl (toolset marketing)
PlanWebsite builder: the Grow plan and up.

Request body

FieldTypeRequiredDescription
contentTypeenumYesOne of image/jpeg, image/png, image/webp.

Example

curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/image-upload-url" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"contentType":"image/jpeg"}'

Response

200: the answer's fields
FieldTypeDescription
signedUploadUrlstring (uri)
urlstring

The website's image library

GET /organizations/{organizationId}/website/media

The business's uploaded images and the stock photos it has used, most recently used first, paged by cursor. stockProviders lists the photo libraries that can be searched (none: stock search is off). Read-only.

Permissionwebsite.read (Owner, Admin, Staff)
Riskread, OAuth scope skuflow.read. Read: reads only.
MCP toolwebsite_media (toolset marketing)

Parameters

NameInTypeRequiredDescription
cursorquerystringNoUp to 100 characters.
limitqueryintegerNo1–200.

Example

curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/media" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
itemsarray of object
items[].idstring
items[].sourceenumOne of UPLOAD, STOCK.
items[].urlstringWhat to put in a section's image field.
items[].thumbUrlstring or null
items[].altstring
items[].widthinteger or null
items[].heightinteger or null
items[].providerstring or nullStock: UNSPLASH or PEXELS.
items[].providerIdstring or null
items[].authorstring or nullStock: the photographer, credited on the site.
items[].authorUrlstring or null
items[].sourceUrlstring or null
items[].createdAtstring (date-time)
items[].lastUsedAtstring (date-time)
nextCursorstring or null
stockProvidersarray of enum

Add an uploaded image to the library

POST /organizations/{organizationId}/website/media/uploads

Step 2 of uploading, after the PUT to the signed URL: the image joins the library. url must be one POST /website/image-upload-url gave this business (404 otherwise).

Permissionwebsite.manage (Owner, Admin)
Riskwrite, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolwebsite_confirmImageUpload (toolset marketing)
PlanWebsite builder: the Grow plan and up.

Request body

FieldTypeRequiredDescription
urlstringYesUp to 300 characters.
widthinteger or nullNo1–20000.
heightinteger or nullNo1–20000.
altstring or nullNoUp to 300 characters.

Example

curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/media/uploads" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com"}'

Response

200: the answer's fields
FieldTypeDescription
idstring
sourceenumOne of UPLOAD, STOCK.
urlstringWhat to put in a section's image field.
thumbUrlstring or null
altstring
widthinteger or null
heightinteger or null
providerstring or nullStock: UNSPLASH or PEXELS.
providerIdstring or null
authorstring or nullStock: the photographer, credited on the site.
authorUrlstring or null
sourceUrlstring or null
createdAtstring (date-time)
lastUsedAtstring (date-time)

Search free stock photos

GET /organizations/{organizationId}/website/stock-photos

Landscape photos for query from Unsplash (or Pexels when Unsplash is unavailable; provider picks one), free for commercial use with a credit the site shows. Searching uses nothing; POST /website/media/stock with a result's provider and id to use one. Rate-limited per business. Read-only.

Permissionwebsite.manage (Owner, Admin)
Riskread, OAuth scope skuflow.read. Read: reads only.
MCP toolwebsite_searchStockPhotos (toolset marketing)

Parameters

NameInTypeRequiredDescription
queryquerystringYesUp to 100 characters.
pagequeryintegerNo1–50.
providerqueryenumNoOne of UNSPLASH, PEXELS.

Example

curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/stock-photos?query=string" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
providerenum or nullOne of UNSPLASH, PEXELS.
photosarray of object
photos[].providerenumOne of UNSPLASH, PEXELS.
photos[].idstringPass with provider to POST /website/media/stock to use it.
photos[].urlstring
photos[].thumbUrlstring
photos[].widthinteger
photos[].heightinteger
photos[].altstring
photos[].authorstring
photos[].authorUrlstring
photos[].sourceUrlstring
pageinteger
hasMoreboolean

Use a stock photo

POST /organizations/{organizationId}/website/media/stock

Adds a stock photo (by provider and id from GET /website/stock-photos) to the library with its credit and reports the use to the provider, as its licence asks. Answers the library item: put its url in a section. Using the same photo again answers the same item.

Permissionwebsite.manage (Owner, Admin)
Riskwrite, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolwebsite_useStockPhoto (toolset marketing)
PlanWebsite builder: the Grow plan and up.

Request body

FieldTypeRequiredDescription
providerenumYesOne of UNSPLASH, PEXELS.
photoIdstringYesUp to 100 characters.

Example

curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/media/stock" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"provider":"UNSPLASH","photoId":"photo_id"}'

Response

201: the answer's fields
FieldTypeDescription
idstring
sourceenumOne of UPLOAD, STOCK.
urlstringWhat to put in a section's image field.
thumbUrlstring or null
altstring
widthinteger or null
heightinteger or null
providerstring or nullStock: UNSPLASH or PEXELS.
providerIdstring or null
authorstring or nullStock: the photographer, credited on the site.
authorUrlstring or null
sourceUrlstring or null
createdAtstring (date-time)
lastUsedAtstring (date-time)

Remove an image from the library

DELETE /organizations/{organizationId}/website/media/{mediaId}

Takes the image out of the library. Pages that already show it keep showing it (and keep its credit) until changed.

Permissionwebsite.manage (Owner, Admin)
Risksensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.
MCP toolwebsite_deleteMedia (toolset marketing)
PlanWebsite builder: the Grow plan and up.
ApprovalOver MCP, this tool always waits for your approval in SKUFlow. See Approvals.

Parameters

NameInTypeRequiredDescription
mediaIdpathstringYes

Example

curl -X DELETE "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/media/{mediaId}" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
oktrue

Add a page

POST /organizations/{organizationId}/website/pages

Adds a draft page at the end of the navigation. sections is validated per type. 409 when the address is taken.

Permissionwebsite.manage (Owner, Admin)
Riskwrite, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolwebsite_createPage (toolset marketing)
PlanWebsite builder: the Grow plan and up.

Request body

FieldTypeRequiredDescription
slugstringYesThe page address: "" (home only) or words-with-hyphens. Up to 60 characters.
titlestringYesUp to 120 characters.
showInNavbooleanNo
seoTitlestring or nullNoUp to 70 characters.
seoDescriptionstring or nullNoUp to 170 characters.
sectionsarray of anyNoEvery section of the page in order: { id, type, hidden, props }; replaces the list. Up to 30 items.

Example

curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/pages" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"slug":"string","title":"string"}'

Response

201: the answer's fields
FieldTypeDescription
idstring
slugstringThe page address; "" is the home page.
titlestring
showInNavboolean
sortOrderinteger
seoTitlestring or null
seoDescriptionstring or null
sectionsarray of object
sections[].idstring
sections[].typestringhero, trust, services, about, testimonials, booking (the request form), serviceArea, faq, cta, contact, gallery or text.
sections[].hiddenboolean
sections[].propsobjectThe section's fields; their schema per type is in.
updatedAtstring (date-time)

Edit a page

PATCH /organizations/{organizationId}/website/pages/{pageId}

Changes the fields sent on a draft page; sections replaces the whole list (validated per type; a 400 names the field). The home page keeps its address.

Permissionwebsite.manage (Owner, Admin)
Riskwrite, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolwebsite_updatePage (toolset marketing)
PlanWebsite builder: the Grow plan and up.

Parameters

NameInTypeRequiredDescription
pageIdpathstringYes

Request body

FieldTypeRequiredDescription
slugstringNoThe page address: "" (home only) or words-with-hyphens. Up to 60 characters.
titlestringNoUp to 120 characters.
showInNavbooleanNo
seoTitlestring or nullNoUp to 70 characters.
seoDescriptionstring or nullNoUp to 170 characters.
sectionsarray of anyNoEvery section of the page in order: { id, type, hidden, props }; replaces the list. Up to 30 items.

Example

curl -X PATCH "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/pages/{pageId}" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"slug":"string","title":"string","showInNav":true}'

Response

200: the answer's fields
FieldTypeDescription
idstring
slugstringThe page address; "" is the home page.
titlestring
showInNavboolean
sortOrderinteger
seoTitlestring or null
seoDescriptionstring or null
sectionsarray of object
sections[].idstring
sections[].typestringhero, trust, services, about, testimonials, booking (the request form), serviceArea, faq, cta, contact, gallery or text.
sections[].hiddenboolean
sections[].propsobjectThe section's fields; their schema per type is in.
updatedAtstring (date-time)

Delete a page

DELETE /organizations/{organizationId}/website/pages/{pageId}

Destructive: removes the draft page (the home page cannot be deleted). The live site keeps it until published again.

Permissionwebsite.manage (Owner, Admin)
Risksensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.
MCP toolwebsite_deletePage (toolset marketing)
PlanWebsite builder: the Grow plan and up.
ApprovalOver MCP, this tool always waits for your approval in SKUFlow. See Approvals.

Parameters

NameInTypeRequiredDescription
pageIdpathstringYes

Example

curl -X DELETE "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/pages/{pageId}" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
oktrue

Reorder the pages

POST /organizations/{organizationId}/website/pages/order

Sets the navigation order: pageIds lists every page of the site once.

Permissionwebsite.manage (Owner, Admin)
Riskwrite, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolwebsite_reorderPages (toolset marketing)
PlanWebsite builder: the Grow plan and up.

Request body

FieldTypeRequiredDescription
pageIdsarray of stringYesUp to 50 items.

Example

curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/pages/order" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"pageIds":["page_id"]}'

Response

200: the answer's fields
FieldTypeDescription
idstring
subdomainstring
statusenumOne of DRAFT, PUBLISHED, UNPUBLISHED.
themeobject
theme.primaryColorstring
theme.accentColorstring
theme.fontenumOne of modern, classic, friendly, bold, elegant, geometric.
theme.radiusenumOne of square, soft, round.
theme.headerStyleenumOne of light, dark, brand.
theme.stylestringUp to 40 characters.
profileobject
profile.taglinestringUp to 160 characters.
profile.phonestringUp to 40 characters.
profile.emailempty string or string (email)
profile.addressstringUp to 300 characters.
profile.hoursobject
profile.hoursNotestringUp to 200 characters.
profile.licenseTextstringUp to 200 characters.
profile.serviceAreaTextstringUp to 600 characters.
profile.socialobject
profile.social.facebookempty string or string (uri)
profile.social.instagramempty string or string (uri)
profile.social.googleempty string or string (uri)
profile.social.yelpempty string or string (uri)
profile.social.nextdoorempty string or string (uri)
profile.logoUrlstringUp to 2000 characters.
profile.headerBrandenumOne of logoAndName, logo, name.
profile.logoSizeenumOne of small, medium, large.
profile.siteNamestringUp to 120 characters.
profile.privacyUrlempty string or string (uri)
profile.termsUrlempty string or string (uri)
profile.footerobject
profile.footer.showTaglineboolean
profile.footer.showContactboolean
profile.footer.showHoursboolean
profile.footer.showSocialboolean
profile.footer.showPoweredByboolean
profile.footer.copyrightstringUp to 200 characters.
seoTitlestring or null
seoDescriptionstring or null
publishedAtstring (date-time) or null
generatedBystring or nullAI (written by Claude) or TEMPLATE.
tradestring or nullThe trade template it was built from (e.g. screen-printing, embroidery); null when none.
defaultUrlstring or nullhttps://{subdomain}.{sites domain}, when one is configured.
pathstring/sites/{subdomain} on the app: always works.
hasUnpublishedChangesboolean
pagesarray of object
pages[].idstring
pages[].slugstringThe page address; "" is the home page.
pages[].titlestring
pages[].showInNavboolean
pages[].sortOrderinteger
pages[].seoTitlestring or null
pages[].seoDescriptionstring or null
pages[].sectionsarray of object
pages[].sections[].idstring
pages[].sections[].typestringhero, trust, services, about, testimonials, booking (the request form), serviceArea, faq, cta, contact, gallery or text.
pages[].sections[].hiddenboolean
pages[].sections[].propsobjectThe section's fields; their schema per type is in.
pages[].updatedAtstring (date-time)
domainsarray of object
domains[].idstring
domains[].hostnamestring
domains[].statusenumOne of PENDING, ACTIVE, FAILED.
domains[].verificationTokenstringThe value of the TXT record at recordName.
domains[].recordNamestring
domains[].cnameTargetstring or nullWhere the domain's CNAME (or A records) must point.
domains[].apexbooleanA bare domain (example.com): A records instead of a CNAME.
domains[].recordsarray of objectEvery DNS record to add: the ownership TXT, then the CNAME (or A records).
domains[].records[].typeenumOne of TXT, CNAME, A.
domains[].records[].namestringRelative to the domain, as DNS providers ask: "@", "www", "_skuflow.www".
domains[].records[].fullNamestring
domains[].records[].valuestring
domains[].records[].purposeenumOne of verify, route.
domains[].verifiedAtstring (date-time) or null
domains[].lastCheckedAtstring (date-time) or null
domains[].lastErrorstring or null
domains[].isPrimaryboolean
domains[].createdAtstring (date-time)
createdAtstring (date-time)
updatedAtstring (date-time)

Connect a custom domain

POST /organizations/{organizationId}/website/domains

Adds a domain (e.g. www.example.com) as PENDING. The business then adds every record in records: the ownership TXT and a CNAME to cnameTarget (A records for a bare domain); the domain becomes ACTIVE (served, certificate on demand) once the checks pass, checked every ten minutes or with POST …/verify. Up to five per site.

Permissionwebsite.manage (Owner, Admin)
Riskwrite, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolwebsite_addDomain (toolset marketing)
PlanCustom domain: the Grow plan and up.

Request body

FieldTypeRequiredDescription
hostnamestringYesUp to 260 characters.

Example

curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/domains" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"hostname":"string"}'

Response

201: the answer's fields
FieldTypeDescription
idstring
subdomainstring
statusenumOne of DRAFT, PUBLISHED, UNPUBLISHED.
themeobject
theme.primaryColorstring
theme.accentColorstring
theme.fontenumOne of modern, classic, friendly, bold, elegant, geometric.
theme.radiusenumOne of square, soft, round.
theme.headerStyleenumOne of light, dark, brand.
theme.stylestringUp to 40 characters.
profileobject
profile.taglinestringUp to 160 characters.
profile.phonestringUp to 40 characters.
profile.emailempty string or string (email)
profile.addressstringUp to 300 characters.
profile.hoursobject
profile.hoursNotestringUp to 200 characters.
profile.licenseTextstringUp to 200 characters.
profile.serviceAreaTextstringUp to 600 characters.
profile.socialobject
profile.social.facebookempty string or string (uri)
profile.social.instagramempty string or string (uri)
profile.social.googleempty string or string (uri)
profile.social.yelpempty string or string (uri)
profile.social.nextdoorempty string or string (uri)
profile.logoUrlstringUp to 2000 characters.
profile.headerBrandenumOne of logoAndName, logo, name.
profile.logoSizeenumOne of small, medium, large.
profile.siteNamestringUp to 120 characters.
profile.privacyUrlempty string or string (uri)
profile.termsUrlempty string or string (uri)
profile.footerobject
profile.footer.showTaglineboolean
profile.footer.showContactboolean
profile.footer.showHoursboolean
profile.footer.showSocialboolean
profile.footer.showPoweredByboolean
profile.footer.copyrightstringUp to 200 characters.
seoTitlestring or null
seoDescriptionstring or null
publishedAtstring (date-time) or null
generatedBystring or nullAI (written by Claude) or TEMPLATE.
tradestring or nullThe trade template it was built from (e.g. screen-printing, embroidery); null when none.
defaultUrlstring or nullhttps://{subdomain}.{sites domain}, when one is configured.
pathstring/sites/{subdomain} on the app: always works.
hasUnpublishedChangesboolean
pagesarray of object
pages[].idstring
pages[].slugstringThe page address; "" is the home page.
pages[].titlestring
pages[].showInNavboolean
pages[].sortOrderinteger
pages[].seoTitlestring or null
pages[].seoDescriptionstring or null
pages[].sectionsarray of object
pages[].sections[].idstring
pages[].sections[].typestringhero, trust, services, about, testimonials, booking (the request form), serviceArea, faq, cta, contact, gallery or text.
pages[].sections[].hiddenboolean
pages[].sections[].propsobjectThe section's fields; their schema per type is in.
pages[].updatedAtstring (date-time)
domainsarray of object
domains[].idstring
domains[].hostnamestring
domains[].statusenumOne of PENDING, ACTIVE, FAILED.
domains[].verificationTokenstringThe value of the TXT record at recordName.
domains[].recordNamestring
domains[].cnameTargetstring or nullWhere the domain's CNAME (or A records) must point.
domains[].apexbooleanA bare domain (example.com): A records instead of a CNAME.
domains[].recordsarray of objectEvery DNS record to add: the ownership TXT, then the CNAME (or A records).
domains[].records[].typeenumOne of TXT, CNAME, A.
domains[].records[].namestringRelative to the domain, as DNS providers ask: "@", "www", "_skuflow.www".
domains[].records[].fullNamestring
domains[].records[].valuestring
domains[].records[].purposeenumOne of verify, route.
domains[].verifiedAtstring (date-time) or null
domains[].lastCheckedAtstring (date-time) or null
domains[].lastErrorstring or null
domains[].isPrimaryboolean
domains[].createdAtstring (date-time)
createdAtstring (date-time)
updatedAtstring (date-time)

Check a domain's DNS now

POST /organizations/{organizationId}/website/domains/{domainId}/verify

Runs the DNS checks for one domain now; lastError says what is missing. ACTIVE domains serve the site.

Permissionwebsite.manage (Owner, Admin)
Riskwrite, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolwebsite_verifyDomain (toolset marketing)
PlanCustom domain: the Grow plan and up.

Parameters

NameInTypeRequiredDescription
domainIdpathstringYes

Example

curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/domains/{domainId}/verify" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
idstring
subdomainstring
statusenumOne of DRAFT, PUBLISHED, UNPUBLISHED.
themeobject
theme.primaryColorstring
theme.accentColorstring
theme.fontenumOne of modern, classic, friendly, bold, elegant, geometric.
theme.radiusenumOne of square, soft, round.
theme.headerStyleenumOne of light, dark, brand.
theme.stylestringUp to 40 characters.
profileobject
profile.taglinestringUp to 160 characters.
profile.phonestringUp to 40 characters.
profile.emailempty string or string (email)
profile.addressstringUp to 300 characters.
profile.hoursobject
profile.hoursNotestringUp to 200 characters.
profile.licenseTextstringUp to 200 characters.
profile.serviceAreaTextstringUp to 600 characters.
profile.socialobject
profile.social.facebookempty string or string (uri)
profile.social.instagramempty string or string (uri)
profile.social.googleempty string or string (uri)
profile.social.yelpempty string or string (uri)
profile.social.nextdoorempty string or string (uri)
profile.logoUrlstringUp to 2000 characters.
profile.headerBrandenumOne of logoAndName, logo, name.
profile.logoSizeenumOne of small, medium, large.
profile.siteNamestringUp to 120 characters.
profile.privacyUrlempty string or string (uri)
profile.termsUrlempty string or string (uri)
profile.footerobject
profile.footer.showTaglineboolean
profile.footer.showContactboolean
profile.footer.showHoursboolean
profile.footer.showSocialboolean
profile.footer.showPoweredByboolean
profile.footer.copyrightstringUp to 200 characters.
seoTitlestring or null
seoDescriptionstring or null
publishedAtstring (date-time) or null
generatedBystring or nullAI (written by Claude) or TEMPLATE.
tradestring or nullThe trade template it was built from (e.g. screen-printing, embroidery); null when none.
defaultUrlstring or nullhttps://{subdomain}.{sites domain}, when one is configured.
pathstring/sites/{subdomain} on the app: always works.
hasUnpublishedChangesboolean
pagesarray of object
pages[].idstring
pages[].slugstringThe page address; "" is the home page.
pages[].titlestring
pages[].showInNavboolean
pages[].sortOrderinteger
pages[].seoTitlestring or null
pages[].seoDescriptionstring or null
pages[].sectionsarray of object
pages[].sections[].idstring
pages[].sections[].typestringhero, trust, services, about, testimonials, booking (the request form), serviceArea, faq, cta, contact, gallery or text.
pages[].sections[].hiddenboolean
pages[].sections[].propsobjectThe section's fields; their schema per type is in.
pages[].updatedAtstring (date-time)
domainsarray of object
domains[].idstring
domains[].hostnamestring
domains[].statusenumOne of PENDING, ACTIVE, FAILED.
domains[].verificationTokenstringThe value of the TXT record at recordName.
domains[].recordNamestring
domains[].cnameTargetstring or nullWhere the domain's CNAME (or A records) must point.
domains[].apexbooleanA bare domain (example.com): A records instead of a CNAME.
domains[].recordsarray of objectEvery DNS record to add: the ownership TXT, then the CNAME (or A records).
domains[].records[].typeenumOne of TXT, CNAME, A.
domains[].records[].namestringRelative to the domain, as DNS providers ask: "@", "www", "_skuflow.www".
domains[].records[].fullNamestring
domains[].records[].valuestring
domains[].records[].purposeenumOne of verify, route.
domains[].verifiedAtstring (date-time) or null
domains[].lastCheckedAtstring (date-time) or null
domains[].lastErrorstring or null
domains[].isPrimaryboolean
domains[].createdAtstring (date-time)
createdAtstring (date-time)
updatedAtstring (date-time)

Make a domain the main address

POST /organizations/{organizationId}/website/domains/{domainId}/primary

The site's canonical address (search engines, sitemap) becomes this domain once it is ACTIVE.

Permissionwebsite.manage (Owner, Admin)
Riskwrite, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolwebsite_setPrimaryDomain (toolset marketing)
PlanCustom domain: the Grow plan and up.

Parameters

NameInTypeRequiredDescription
domainIdpathstringYes

Example

curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/domains/{domainId}/primary" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
idstring
subdomainstring
statusenumOne of DRAFT, PUBLISHED, UNPUBLISHED.
themeobject
theme.primaryColorstring
theme.accentColorstring
theme.fontenumOne of modern, classic, friendly, bold, elegant, geometric.
theme.radiusenumOne of square, soft, round.
theme.headerStyleenumOne of light, dark, brand.
theme.stylestringUp to 40 characters.
profileobject
profile.taglinestringUp to 160 characters.
profile.phonestringUp to 40 characters.
profile.emailempty string or string (email)
profile.addressstringUp to 300 characters.
profile.hoursobject
profile.hoursNotestringUp to 200 characters.
profile.licenseTextstringUp to 200 characters.
profile.serviceAreaTextstringUp to 600 characters.
profile.socialobject
profile.social.facebookempty string or string (uri)
profile.social.instagramempty string or string (uri)
profile.social.googleempty string or string (uri)
profile.social.yelpempty string or string (uri)
profile.social.nextdoorempty string or string (uri)
profile.logoUrlstringUp to 2000 characters.
profile.headerBrandenumOne of logoAndName, logo, name.
profile.logoSizeenumOne of small, medium, large.
profile.siteNamestringUp to 120 characters.
profile.privacyUrlempty string or string (uri)
profile.termsUrlempty string or string (uri)
profile.footerobject
profile.footer.showTaglineboolean
profile.footer.showContactboolean
profile.footer.showHoursboolean
profile.footer.showSocialboolean
profile.footer.showPoweredByboolean
profile.footer.copyrightstringUp to 200 characters.
seoTitlestring or null
seoDescriptionstring or null
publishedAtstring (date-time) or null
generatedBystring or nullAI (written by Claude) or TEMPLATE.
tradestring or nullThe trade template it was built from (e.g. screen-printing, embroidery); null when none.
defaultUrlstring or nullhttps://{subdomain}.{sites domain}, when one is configured.
pathstring/sites/{subdomain} on the app: always works.
hasUnpublishedChangesboolean
pagesarray of object
pages[].idstring
pages[].slugstringThe page address; "" is the home page.
pages[].titlestring
pages[].showInNavboolean
pages[].sortOrderinteger
pages[].seoTitlestring or null
pages[].seoDescriptionstring or null
pages[].sectionsarray of object
pages[].sections[].idstring
pages[].sections[].typestringhero, trust, services, about, testimonials, booking (the request form), serviceArea, faq, cta, contact, gallery or text.
pages[].sections[].hiddenboolean
pages[].sections[].propsobjectThe section's fields; their schema per type is in.
pages[].updatedAtstring (date-time)
domainsarray of object
domains[].idstring
domains[].hostnamestring
domains[].statusenumOne of PENDING, ACTIVE, FAILED.
domains[].verificationTokenstringThe value of the TXT record at recordName.
domains[].recordNamestring
domains[].cnameTargetstring or nullWhere the domain's CNAME (or A records) must point.
domains[].apexbooleanA bare domain (example.com): A records instead of a CNAME.
domains[].recordsarray of objectEvery DNS record to add: the ownership TXT, then the CNAME (or A records).
domains[].records[].typeenumOne of TXT, CNAME, A.
domains[].records[].namestringRelative to the domain, as DNS providers ask: "@", "www", "_skuflow.www".
domains[].records[].fullNamestring
domains[].records[].valuestring
domains[].records[].purposeenumOne of verify, route.
domains[].verifiedAtstring (date-time) or null
domains[].lastCheckedAtstring (date-time) or null
domains[].lastErrorstring or null
domains[].isPrimaryboolean
domains[].createdAtstring (date-time)
createdAtstring (date-time)
updatedAtstring (date-time)

Disconnect a domain

DELETE /organizations/{organizationId}/website/domains/{domainId}

Destructive: the domain stops serving the site at once.

Permissionwebsite.manage (Owner, Admin)
Risksensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access.
MCP toolwebsite_removeDomain (toolset marketing)
ApprovalOver MCP, this tool always waits for your approval in SKUFlow. See Approvals.

Parameters

NameInTypeRequiredDescription
domainIdpathstringYes

Example

curl -X DELETE "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/domains/{domainId}" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY"

Response

200: the answer's fields
FieldTypeDescription
idstring
subdomainstring
statusenumOne of DRAFT, PUBLISHED, UNPUBLISHED.
themeobject
theme.primaryColorstring
theme.accentColorstring
theme.fontenumOne of modern, classic, friendly, bold, elegant, geometric.
theme.radiusenumOne of square, soft, round.
theme.headerStyleenumOne of light, dark, brand.
theme.stylestringUp to 40 characters.
profileobject
profile.taglinestringUp to 160 characters.
profile.phonestringUp to 40 characters.
profile.emailempty string or string (email)
profile.addressstringUp to 300 characters.
profile.hoursobject
profile.hoursNotestringUp to 200 characters.
profile.licenseTextstringUp to 200 characters.
profile.serviceAreaTextstringUp to 600 characters.
profile.socialobject
profile.social.facebookempty string or string (uri)
profile.social.instagramempty string or string (uri)
profile.social.googleempty string or string (uri)
profile.social.yelpempty string or string (uri)
profile.social.nextdoorempty string or string (uri)
profile.logoUrlstringUp to 2000 characters.
profile.headerBrandenumOne of logoAndName, logo, name.
profile.logoSizeenumOne of small, medium, large.
profile.siteNamestringUp to 120 characters.
profile.privacyUrlempty string or string (uri)
profile.termsUrlempty string or string (uri)
profile.footerobject
profile.footer.showTaglineboolean
profile.footer.showContactboolean
profile.footer.showHoursboolean
profile.footer.showSocialboolean
profile.footer.showPoweredByboolean
profile.footer.copyrightstringUp to 200 characters.
seoTitlestring or null
seoDescriptionstring or null
publishedAtstring (date-time) or null
generatedBystring or nullAI (written by Claude) or TEMPLATE.
tradestring or nullThe trade template it was built from (e.g. screen-printing, embroidery); null when none.
defaultUrlstring or nullhttps://{subdomain}.{sites domain}, when one is configured.
pathstring/sites/{subdomain} on the app: always works.
hasUnpublishedChangesboolean
pagesarray of object
pages[].idstring
pages[].slugstringThe page address; "" is the home page.
pages[].titlestring
pages[].showInNavboolean
pages[].sortOrderinteger
pages[].seoTitlestring or null
pages[].seoDescriptionstring or null
pages[].sectionsarray of object
pages[].sections[].idstring
pages[].sections[].typestringhero, trust, services, about, testimonials, booking (the request form), serviceArea, faq, cta, contact, gallery or text.
pages[].sections[].hiddenboolean
pages[].sections[].propsobjectThe section's fields; their schema per type is in.
pages[].updatedAtstring (date-time)
domainsarray of object
domains[].idstring
domains[].hostnamestring
domains[].statusenumOne of PENDING, ACTIVE, FAILED.
domains[].verificationTokenstringThe value of the TXT record at recordName.
domains[].recordNamestring
domains[].cnameTargetstring or nullWhere the domain's CNAME (or A records) must point.
domains[].apexbooleanA bare domain (example.com): A records instead of a CNAME.
domains[].recordsarray of objectEvery DNS record to add: the ownership TXT, then the CNAME (or A records).
domains[].records[].typeenumOne of TXT, CNAME, A.
domains[].records[].namestringRelative to the domain, as DNS providers ask: "@", "www", "_skuflow.www".
domains[].records[].fullNamestring
domains[].records[].valuestring
domains[].records[].purposeenumOne of verify, route.
domains[].verifiedAtstring (date-time) or null
domains[].lastCheckedAtstring (date-time) or null
domains[].lastErrorstring or null
domains[].isPrimaryboolean
domains[].createdAtstring (date-time)
createdAtstring (date-time)
updatedAtstring (date-time)

Add an image to the website library (content in the request)

POST /organizations/{organizationId}/website/media/content

Adds a JPEG, PNG or WebP image to the website's library in one call: send contentBase64 or a public sourceUrl (up to 10 MB). Returns the library entry; put its url in a section's image field (hero, about, gallery) with website.updatePage. Needs a website (website.create first).

Permissionwebsite.manage (Owner, Admin)
Riskwrite, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it.
MCP toolwebsite_uploadImage (toolset marketing)
PlanWebsite builder: the Grow plan and up.

Request body

FieldTypeRequiredDescription
altstring or nullNoAlternative text describing the image. Up to 300 characters.
fileNamestringNoThe file's name, e.g. receipt.jpg (default: from the URL, else 'file'). Up to 500 characters.
contentTypestringNoMIME type, e.g. image/jpeg or application/pdf. Optional: taken from a data: URL, the URL's answer or the file's first bytes. Up to 200 characters.
contentBase64stringNoThe file's bytes as base64 (a data: URL is accepted too). Up to 10 MB. Give this or sourceUrl.
sourceUrlstring (uri)NoA public http(s) URL SKUFlow downloads the file from (up to 10 MB, 20 s, 3 redirects; private and internal addresses are refused). Give this or contentBase64. Up to 2000 characters.

Example

curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/website/media/content" \
  -H "Authorization: Bearer $SKUFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"alt":"string","fileName":"string","contentType":"string"}'

Response

201: the answer's fields
FieldTypeDescription
idstring
sourceenumOne of UPLOAD, STOCK.
urlstringWhat to put in a section's image field.
thumbUrlstring or null
altstring
widthinteger or null
heightinteger or null
providerstring or nullStock: UNSPLASH or PEXELS.
providerIdstring or null
authorstring or nullStock: the photographer, credited on the site.
authorUrlstring or null
sourceUrlstring or null
createdAtstring (date-time)
lastUsedAtstring (date-time)

On this page