API reference/Sites
Create a site from a template
Try itMakes a new DRAFT site from a template — the same engine as the console's new-site flow. It adds the package's wholesale setup fee (if any) to your bill now and the monthly fee once the site is live. Nothing is public until you publish. Send expected_setup_cents/expected_monthly_cents to refuse if the price changed since you quoted it.
POST
/api/v1/sitesAuthentication
An API key as Authorization: Bearer or x-api-key. It needs the sites:create scope — make new sites (each adds the wholesale fee to your bill).
sites:createAdds to your billIdempotency-Key requiredMCP tool: create_site
Parameters
Named placeholders go in the path; the rest in a JSON body.
template_idstringBody · required- From List templates.1 to 100 characters
namestringBody · required- The site's name in your account, e.g. the business name.2 to 80 characters
slugstringBody · optional- The free address's subdomain. Taken → a number is added. Omitted = from the name.
client_idstringBody · optional- The client it is for (List clients).At most 100 characters
package_idstringBody · optional- From List packages. Omitted = the default package.At most 100 characters
stylestringBody · optional- A design style slug. Omitted = the template's own look.One of: altered, clean-modern, warm-classic, industrial, luxe, fresh-bright, coastal, heritage
business_namestringBody · optional- Written into the site's business details.1 to 120 characters
retail_setup_centsintegerBody · optional- Your price to the client, setup. Needs a creator who may see prices.0 to 100000000
retail_monthly_centsintegerBody · optional- Your price to the client, monthly. Needs a creator who may see prices.0 to 100000000
expected_setup_centsintegerBody · optional- Refuse unless the wholesale setup fee is exactly this.0 to 100000000
expected_monthly_centsintegerBody · optional- Refuse unless the wholesale monthly fee is exactly this.0 to 100000000
Response
201 with JSON on success (schema on the right). Errors use the standard envelope; a retry with the same Idempotency-Key gets the first answer back (how retries work).
curl -X POST 'https://websites.workflowcorp.com/api/v1/sites' \
-H "Authorization: Bearer $WEBSITEBUDDY_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"template_id":"TEMPLATE_ID","name":"Maple Street Bakery","client_id":"CLIENT_ID","style":"warm-classic"}'{
"template_id": "TEMPLATE_ID",
"name": "Maple Street Bakery",
"client_id": "CLIENT_ID",
"style": "warm-classic"
}{
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"slug": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"draft",
"live",
"suspended",
"archived"
]
},
"taken_down": {
"type": "boolean",
"description": "You took the site down (status suspended): not served, not billed from the next run, data kept. put_site_back_up reverses it."
},
"address": {
"type": "string",
"description": "The free address, e.g. https://rosies-diner.websites.workflowcorp.com/"
},
"custom_domain": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The verified primary custom domain, if any."
},
"client_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"template_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"package": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"page_limit": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
}
},
"required": [
"id",
"name",
"page_limit"
],
"additionalProperties": false
},
{
"type": "null"
}
]
},
"published_version": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
]
},
"published_at": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
]
},
"unpublished_changes": {
"type": "boolean",
"description": "The draft has edits that are not live yet."
},
"editor_url": {
"type": "string"
},
"prices": {
"anyOf": [
{
"type": "object",
"properties": {
"wholesale_setup_cents": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"wholesale_monthly_cents": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"retail_setup_cents": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"retail_monthly_cents": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
"wholesale_setup_cents",
"wholesale_monthly_cents",
"retail_setup_cents",
"retail_monthly_cents"
],
"additionalProperties": false
},
{
"type": "null"
}
],
"description": "Only when the key's creator may see prices (billing.view); null otherwise."
},
"is_sample": {
"type": "boolean"
},
"created_at": {
"type": "string"
},
"page_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"template_page_count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "More than page_count when the package's page limit trimmed the template."
}
},
"required": [
"id",
"name",
"slug",
"status",
"taken_down",
"address",
"custom_domain",
"client_id",
"template_id",
"package",
"published_version",
"published_at",
"unpublished_changes",
"editor_url",
"prices",
"is_sample",
"created_at",
"page_count",
"template_page_count"
],
"additionalProperties": false
}