---
title: "Create a space"
method: POST
path: "/v1/spaces"
tags: ["Spaces"]
---

# Create a space

`POST /v1/spaces`

## Request

- Base URL: `https://api.spacefast.com`
- URL: `https://api.spacefast.com/v1/spaces`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://api.spacefast.com/v1/auth/oauth2/authorize`, token URL `https://api.spacefast.com/v1/auth/oauth2/token`; client credentials, token URL `https://api.spacefast.com/v1/auth/oauth2/token`, scopes: `spaces:write`)

Creates a space under a team with a chosen or generated slug. Pass `source` to create it from a GitHub repository and start its first build. Use POST /v1/publish to create a space and publish content in one call.

## Request body

- object
  - `teamId` string, nullable
  - `principal` object
    - `type` 'team' | 'external', required: Owning principal kind.
    - `id` string, required: Tenant-local principal id: a team id or an integrator external customer id.
  - `slug` string
  - `title` string
  - `config` object: Initial SpaceConfig overlay for the new space.
    - `index` union: Directory index file; false disables index resolution.
      - string
      - false
    - `fallback` union: Fallback document. "/index.html" means SPA. Defaults to the nearest 404.html.
      - string
      - object
        - `path` string, required: Committed file served when no exact route matches.
        - `status` integer, required: Response status for the fallback.
    - `cleanUrls` boolean: Serve flat `<name>.html` files at their extensionless URL (`/about` serves `about.html`). Defaults to on, unless a 200-status SPA fallback is configured.
    - `listing` boolean: Enable automatic directory listings.
    - `meta` object: Listing, viewer, sharing, and browser icon metadata.
      - `title` string
      - `description` string
      - `image` string
      - `favicon` string
    - `superpowers` object: Platform-managed built-ins and custom JavaScript snippets.
      - `enabled` boolean: Master switch for platform-managed injections.
      - `disable_all_injection` boolean: When true, suppresses every platform-managed script/tag injection.
      - `googleAnalytics` object
        - `enabled` boolean
        - `measurementId` string
      - `googleTagManager` object
        - `enabled` boolean
        - `containerId` string
      - `javascriptTags` object[]
        - `id` string
        - `name` string
        - `enabled` boolean
        - `code` string, required
      - `tags` object
        - `inheritance` object
          - `inherited` boolean
          - `overrides` object[]
            - `tagId` string, required
            - `disabled` boolean
            - `reason` string, nullable
        - `requireReview` boolean: When true, integration changes must go through review before release.
    - `templates` string[]: Files that receive {{ vars.NAME }} substitution at finalize.
    - `theme` object: Visual tokens for every Spacefast-authored page.
      - `accent` string: Accent color for Spacefast-authored pages.
      - `background` string: Background color for Spacefast-authored pages.
      - `logo` string: Logo image (https URL or root-relative path) shown in the brand row.
      - `name` string: Display name shown in the brand row of Pages defaults.
      - `font` string: Font-family stack applied to Spacefast-authored pages.
      - `hideSpacefastBranding` boolean: Remove the Spacefast badge from default pages when the plan permits it.
    - `collab` object: Comments overlay delivery. `default` injects Spacefast's UI; `custom` injects only /__spacefast/collab.css for a self-built UI. Turning comments off lives in the Space's Comments settings, not here.
      - `ui` 'default' | 'custom'
    - `build` object: Default settings for remote repository builds.
      - `rootDirectory` string, nullable
      - `installDirectory` string, nullable
      - `installCommand` string, nullable
      - `buildCommand` string, nullable
      - `outputDirectory` string, nullable
      - `ignoredBuildCommand` string, nullable
      - `frameworkPreset` string, nullable
      - `platformPreset` string, nullable
      - `allowUnsupportedPlatformFeatures` boolean
      - `timeoutSeconds` integer
    - `placement` object: Placement controls for this space.
      - `burstable` boolean
      - `edge` boolean: Run the redirects and headers the edge can answer at the edge, ahead of the space. Takes effect at the next publish. Off by default; the rules the edge cannot answer faithfully stay with the space either way.
    - `markdownNegotiation` boolean: Accepted serving flag; runtime enforcement ships separately.
    - `firewall` object[]: Requests to block or challenge before they reach the space.
      - `name` string: Name for this rule: lowercase letters, digits, `-` and `_`, up to 61 characters. Names the rule in the CLI and the API.
      - `description` string: What this rule is for.
      - `action` 'block' | 'challenge', required: `block` answers without reaching the space; `challenge` asks for proof of a human.
      - `status` integer: Status a blocked request gets. Defaults to 403. Blocks only.
      - `match` TrafficRuleMatch, required: Request attributes the rule looks at. At least one.
        - `path` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
          - string
          - string[]
          - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
            - `op` 'eq' | 'neq' | 'in' | 'inCidr' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'exists', required: How the request attribute is compared to the value.
            - `value` string: Single value to compare against.
            - `values` string[]: Values to compare against, for `in` and `inCidr`.
            - `not` boolean: Match when the comparison does not hold.
        - `host` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
          - string
          - string[]
          - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
            - `op` 'eq' | 'neq' | 'in' | 'inCidr' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'exists', required: How the request attribute is compared to the value.
            - `value` string: Single value to compare against.
            - `values` string[]: Values to compare against, for `in` and `inCidr`.
            - `not` boolean: Match when the comparison does not hold.
        - `method` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
          - string
          - string[]
          - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
            - `op` 'eq' | 'neq' | 'in' | 'inCidr' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'exists', required: How the request attribute is compared to the value.
            - `value` string: Single value to compare against.
            - `values` string[]: Values to compare against, for `in` and `inCidr`.
            - `not` boolean: Match when the comparison does not hold.
        - `ip` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
          - string
          - string[]
          - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
            - `op` 'eq' | 'neq' | 'in' | 'inCidr' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'exists', required: How the request attribute is compared to the value.
            - `value` string: Single value to compare against.
            - `values` string[]: Values to compare against, for `in` and `inCidr`.
            - `not` boolean: Match when the comparison does not hold.
        - `country` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
          - string
          - string[]
          - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
            - `op` 'eq' | 'neq' | 'in' | 'inCidr' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'exists', required: How the request attribute is compared to the value.
            - `value` string: Single value to compare against.
            - `values` string[]: Values to compare against, for `in` and `inCidr`.
            - `not` boolean: Match when the comparison does not hold.
        - `asn` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
          - string
          - string[]
          - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
            - `op` 'eq' | 'neq' | 'in' | 'inCidr' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'exists', required: How the request attribute is compared to the value.
            - `value` string: Single value to compare against.
            - `values` string[]: Values to compare against, for `in` and `inCidr`.
            - `not` boolean: Match when the comparison does not hold.
        - `userAgent` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
          - string
          - string[]
          - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
            - `op` 'eq' | 'neq' | 'in' | 'inCidr' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'exists', required: How the request attribute is compared to the value.
            - `value` string: Single value to compare against.
            - `values` string[]: Values to compare against, for `in` and `inCidr`.
            - `not` boolean: Match when the comparison does not hold.
        - `referer` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
          - string
          - string[]
          - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
            - `op` 'eq' | 'neq' | 'in' | 'inCidr' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'exists', required: How the request attribute is compared to the value.
            - `value` string: Single value to compare against.
            - `values` string[]: Values to compare against, for `in` and `inCidr`.
            - `not` boolean: Match when the comparison does not hold.
        - `header` object: Per-name conditions: { "x-api-client": { "op": "exists" } }.
        - `cookie` object: Per-name conditions: { "x-api-client": { "op": "exists" } }.
        - `query` object: Per-name conditions: { "x-api-client": { "op": "exists" } }.
        - `extension` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
          - string
          - string[]
          - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
            - `op` 'eq' | 'neq' | 'in' | 'inCidr' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'exists', required: How the request attribute is compared to the value.
            - `value` string: Single value to compare against.
            - `values` string[]: Values to compare against, for `in` and `inCidr`.
            - `not` boolean: Match when the comparison does not hold.
        - `ja3` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
          - string
          - string[]
          - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
            - `op` 'eq' | 'neq' | 'in' | 'inCidr' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'exists', required: How the request attribute is compared to the value.
            - `value` string: Single value to compare against.
            - `values` string[]: Values to compare against, for `in` and `inCidr`.
            - `not` boolean: Match when the comparison does not hold.
        - `ja4` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
          - string
          - string[]
          - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
            - `op` 'eq' | 'neq' | 'in' | 'inCidr' | 'contains' | 'startsWith' | 'endsWith' | 'wildcard' | 'exists', required: How the request attribute is compared to the value.
            - `value` string: Single value to compare against.
            - `values` string[]: Values to compare against, for `in` and `inCidr`.
            - `not` boolean: Match when the comparison does not hold.
      - `any` boolean: Fire when any match field holds. Defaults to false: all of them have to.
    - `cache` object: Cache behavior, including which requests skip it.
      - `bypass` object[]: Requests that skip the cache, in order. At most 50.
        - `name` string: Name for this rule: lowercase letters, digits, `-` and `_`, up to 61 characters. Names the rule in the CLI and the API.
        - `description` string: What this rule is for.
        - `match` TrafficRuleMatch, required: Request attributes the rule looks at. At least one.
          - `path` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
            - string
            - string[]
            - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
              - …
          - `host` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
            - string
            - string[]
            - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
              - …
          - `method` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
            - string
            - string[]
            - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
              - …
          - `ip` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
            - string
            - string[]
            - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
              - …
          - `country` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
            - string
            - string[]
            - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
              - …
          - `asn` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
            - string
            - string[]
            - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
              - …
          - `userAgent` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
            - string
            - string[]
            - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
              - …
          - `referer` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
            - string
            - string[]
            - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
              - …
          - `header` object: Per-name conditions: { "x-api-client": { "op": "exists" } }.
          - `cookie` object: Per-name conditions: { "x-api-client": { "op": "exists" } }.
          - `query` object: Per-name conditions: { "x-api-client": { "op": "exists" } }.
          - `extension` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
            - string
            - string[]
            - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
              - …
          - `ja3` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
            - string
            - string[]
            - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
              - …
          - `ja4` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
            - string
            - string[]
            - TrafficRuleClause: An explicit comparison, for the operators the shorthands cannot express.
              - …
        - `any` boolean: Fire when any match field holds. Defaults to false: all of them have to.
    - `redirects` object[]: Browser redirect rules. Same matcher grammar as _redirects, and _redirects rules match first.
      - `source` string, required: Request path to match. * is a splat, :name captures a segment.
      - `destination` string, required: Path or absolute URL. :splat and :name from the source are substituted.
      - `status` 301 | 302 | 303 | 307 | 308: Redirect status, 302 when omitted. To serve other content under this URL, use rewrites.
      - `force` boolean: Answer even when the request path resolves to a committed file, the ! of a _redirects rule.
      - `query` object: Query parameters the request must carry, as parameter name to capture name: { "id": "id" } is the name=:capture token id=:id.
    - `rewrites` object[]: Rewrite and proxy rules: the URL stays, the content comes from the destination. _redirects rules match first, then redirects.
      - `source` string, required: Request path to match. * is a splat, :name captures a segment.
      - `destination` string, required: Path to serve under this URL, or an absolute URL to proxy. :splat and :name from the source are substituted.
      - `cache` 'shared': Let shared caches store the proxy response. Absolute-URL destinations only.
      - `force` boolean: Answer even when the request path resolves to a committed file, the ! of a _redirects rule.
      - `query` object: Query parameters the request must carry, as parameter name to capture name: { "id": "id" } is the name=:capture token id=:id.
      - `notFound` boolean: Serve the destination with status 404, the 404 of a _redirects rule. The destination must be a path.
    - `headers` object[]: Response headers to set or remove on matching requests. A _headers rule wins on the same header name.
      - `source` string, required: Request path to match.
      - `headers` union[], required
        - union
          - object
            - `key` string, required
            - `value` string, required
          - object
            - `key` string, required
            - `remove` true, required: Remove this header instead of setting it, the !Name line of a _headers block.
    - `users` object
      - `enabled` boolean, required
      - `providers` object, required
        - `google` union, required
          - object
            - `mode` 'disabled', required
          - object
            - `mode` 'managed', required
          - object
            - `mode` 'direct', required
            - `clientId` string, required
        - `gravatar` object, required
          - `enabled` boolean, required
        - `spacefast` object, required
          - `enabled` boolean, required
    - `dataSources` object: Named public WordPress sources exposed to repository builds; at most 32 entries.
  - `access` 'private' | 'team' | 'public': Set the initial root access for this new team-owned Space. Omit this field to use the team's default.
  - `dataLocation` string: Data location for a new Space; "auto" lets placement decide.
  - `source` union: Create from an authorized GitHub repository or fork the main branch of a Source available Spacefast repository. GitHub connections start their initial sync and deployment; remixes copy main and publish an initial live build. Team-owned Spaces only.
    - object
      - `provider` 'github', required
      - `installationId` string, required: GitHub App installation that holds the repository.
      - `repositoryId` string, required: Immutable GitHub repository id.
      - `repositoryFullName` string, required: The repository as owner/name.
      - `branch` string: Production branch. Defaults to the repository's default branch.
    - object
      - `provider` 'spacefast_fork', required
      - `url` string, uri, required: Spacefast source URL or dashboard remix link. Forks main into an independent repository, then builds and publishes the copy.

## Response `201`

Response for status 201

- object
  - `$schema` string, uri: Canonical JSON Schema URL for this response body. The server also sends it in the `Link: rel="describedby"` response header.
  - `data` object, required
    - `space` object, required
      - `id` string, required
      - `tenantId` string
      - `mode` 'live' | 'test': `test` when the owning tenant is a linked test tenant, `live` otherwise.
      - `providerRef` string, nullable: WP Cloud `atomic_site_id` of the site serving this space. Use it with `providerClientId` to address the site in WP Cloud. Null until the space is placed.
      - `providerClientId` string, nullable: WP Cloud client identity (`pvc_...`) the space's site is provisioned under.
      - `teamId` string, nullable, required
      - `teamSlug` string, nullable, required
      - `principal` object, nullable
        - `tenantId` string, required
        - `principalType` 'team' | 'external', required
        - `principalId` string, required
      - `infrastructure` object
        - `region` string, nullable, required: Concrete region the space's site was placed in.
        - `runtimeInstanceId` string, nullable, required: Runtime instance serving this space.
        - `managementHostname` string, nullable, required: Permanent hostname minted for the provider site when it was created. It stays attached to the site for the site's whole life and never changes, even when the Space is renamed or gets a custom domain, so it is a stable key for matching this Space to its WP Cloud site. It is not the public URL: visitors use `liveUrl`, and WP Cloud reports the Space's primary hostname as the site's `domain_name`.
        - `provisioningState` 'provisioning' | 'converged' | 'degraded', required: Convergence of the space against its intended infrastructure: still being placed, matching intent, or failing to converge.
      - `anonymous` boolean, required
      - `slug` string, required
      - `title` string, required
      - `status` 'provisioning' | 'active' | 'updating' | 'deleting' | 'failed', required: Operation-lifecycle status. Serving state is the separate `disabled` axis.
      - `disabled` object, nullable, required
        - `at` string, date-time, nullable, required
        - `reasonCode` 'anonymous_expired' | 'publish_failed' | 'abuse_takedown' | 'tenant_suspended' | 'site_suspended' | 'author_removed' | 'archived', required: Why serving is disabled.
      - `claimState` object, nullable, required
        - `expiresAt` string, date-time, nullable, required
        - `claimedAt` string, date-time, nullable, required
        - `purgeAfter` string, date-time, nullable, required
      - `expiryExtension` object, nullable
        - `extendedTo` string, date-time, required
      - `defaultHostname` string, required: Current Spacefast-owned managed hostname: under space.fast, or under view.fast for a space created before space.fast. Renaming the space changes the label and keeps the apex; previously managed hostnames temporarily redirect to the current one.
      - `publicName` string, required: Public space label used in the managed hostname.
      - `liveUrl` string, required: Live space URL: the primary bound domain when one exists, else the default hostname. Always present on non-deleted spaces.
      - `thumbnail` object, nullable, required: Server-selected dashboard thumbnail. Screenshots use WordPress.com mShots; image thumbnails use WordPress.com Site Accelerator.
        - `kind` 'screenshot' | 'image', required
        - `provider` 'wpcom-mshots' | 'wpcom-site-accelerator', required
        - `url` string, uri, required
        - `sourceUrl` string, uri, required
      - `dataLocation` string, required: Resolved data-location region, fixed when the space is created and immutable afterwards; "auto" only while no concrete region is known yet.
      - `region` string, required: Alias of dataLocation for placement dashboards; "auto" only while no concrete region is known yet.
      - `burstable` boolean, nullable, required: Whether this space's site can burst provider PHP workers.
      - `archivedBytes` integer, required: Bytes currently archived out of the hot runtime store.
      - `hasRuntime` boolean, required: Whether this space's live version runs code and therefore has a Runtime surface. Feature eligibility alone does not make the surface visible.
      - `channels` object, required: Channel pointers by name. "live" is present after a version is promoted.
      - `config` object, nullable, required: Stored SpaceConfig overlay applied over the live version's sf.jsonc; null when nothing is overridden.
        - `index` union: Directory index file; false disables index resolution.
          - string
          - false
        - `fallback` union: Fallback document. "/index.html" means SPA. Defaults to the nearest 404.html.
          - string
          - object
            - `path` string, required: Committed file served when no exact route matches.
            - `status` integer, required: Response status for the fallback.
        - `cleanUrls` boolean: Serve flat `<name>.html` files at their extensionless URL (`/about` serves `about.html`). Defaults to on, unless a 200-status SPA fallback is configured.
        - `listing` boolean: Enable automatic directory listings.
        - `meta` object: Listing, viewer, sharing, and browser icon metadata.
          - `title` string
          - `description` string
          - `image` string
          - `favicon` string
        - `superpowers` object: Platform-managed built-ins and custom JavaScript snippets.
          - `enabled` boolean: Master switch for platform-managed injections.
          - `disable_all_injection` boolean: When true, suppresses every platform-managed script/tag injection.
          - `googleAnalytics` object
            - `enabled` boolean
            - `measurementId` string
          - `googleTagManager` object
            - `enabled` boolean
            - `containerId` string
          - `javascriptTags` object[]
            - `id` string
            - `name` string
            - `enabled` boolean
            - `code` string, required
          - `tags` object
            - `inheritance` object
              - …
            - `requireReview` boolean: When true, integration changes must go through review before release.
        - `templates` string[]: Files that receive {{ vars.NAME }} substitution at finalize.
        - `theme` object: Visual tokens for every Spacefast-authored page.
          - `accent` string: Accent color for Spacefast-authored pages.
          - `background` string: Background color for Spacefast-authored pages.
          - `logo` string: Logo image (https URL or root-relative path) shown in the brand row.
          - `name` string: Display name shown in the brand row of Pages defaults.
          - `font` string: Font-family stack applied to Spacefast-authored pages.
          - `hideSpacefastBranding` boolean: Remove the Spacefast badge from default pages when the plan permits it.
        - `collab` object: Comments overlay delivery. `default` injects Spacefast's UI; `custom` injects only /__spacefast/collab.css for a self-built UI. Turning comments off lives in the Space's Comments settings, not here.
          - `ui` 'default' | 'custom', required
        - `build` object: Default settings for remote repository builds.
          - `rootDirectory` string, nullable
          - `installDirectory` string, nullable
          - `installCommand` string, nullable
          - `buildCommand` string, nullable
          - `outputDirectory` string, nullable
          - `ignoredBuildCommand` string, nullable
          - `frameworkPreset` string, nullable
          - `platformPreset` string, nullable
          - `allowUnsupportedPlatformFeatures` boolean
          - `timeoutSeconds` integer
        - `placement` object: Placement controls for this space.
          - `burstable` boolean
          - `edge` boolean: Run the redirects and headers the edge can answer at the edge, ahead of the space. Takes effect at the next publish. Off by default; the rules the edge cannot answer faithfully stay with the space either way.
        - `markdownNegotiation` boolean: Accepted serving flag; runtime enforcement ships separately.
        - `firewall` object[]: Requests to block or challenge before they reach the space.
          - `name` string: Name for this rule: lowercase letters, digits, `-` and `_`, up to 61 characters. Names the rule in the CLI and the API.
          - `description` string: What this rule is for.
          - `action` 'block' | 'challenge', required: `block` answers without reaching the space; `challenge` asks for proof of a human.
          - `status` integer: Status a blocked request gets. Defaults to 403. Blocks only.
          - `match` TrafficRuleMatch, required: Request attributes the rule looks at. At least one.
            - `path` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
              - …
            - `host` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
              - …
            - `method` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
              - …
            - `ip` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
              - …
            - `country` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
              - …
            - `asn` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
              - …
            - `userAgent` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
              - …
            - `referer` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
              - …
            - `header` object: Per-name conditions: { "x-api-client": { "op": "exists" } }.
            - `cookie` object: Per-name conditions: { "x-api-client": { "op": "exists" } }.
            - `query` object: Per-name conditions: { "x-api-client": { "op": "exists" } }.
            - `extension` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
              - …
            - `ja3` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
              - …
            - `ja4` union: What the field has to match. A string with a `*` in it matches as a wildcard, any other string matches exactly, and a list matches any of its values. An `ip` value with a `/` in it matches a CIDR range. Everything else is an explicit clause: { "op": "exists" }, { "op": "contains", "value": "bot" }, { "op": "in", "values": ["RU"], "not": true }.
              - …
          - `any` boolean: Fire when any match field holds. Defaults to false: all of them have to.
        - `cache` object: Cache behavior, including which requests skip it.
          - `bypass` object[]: Requests that skip the cache, in order. At most 50.
            - `name` string: Name for this rule: lowercase letters, digits, `-` and `_`, up to 61 characters. Names the rule in the CLI and the API.
            - `description` string: What this rule is for.
            - `match` TrafficRuleMatch, required: Request attributes the rule looks at. At least one.
              - …
            - `any` boolean: Fire when any match field holds. Defaults to false: all of them have to.
        - `redirects` object[]: Browser redirect rules. Same matcher grammar as _redirects, and _redirects rules match first.
          - `source` string, required: Request path to match. * is a splat, :name captures a segment.
          - `destination` string, required: Path or absolute URL. :splat and :name from the source are substituted.
          - `status` 301 | 302 | 303 | 307 | 308: Redirect status, 302 when omitted. To serve other content under this URL, use rewrites.
          - `force` boolean: Answer even when the request path resolves to a committed file, the ! of a _redirects rule.
          - `query` object: Query parameters the request must carry, as parameter name to capture name: { "id": "id" } is the name=:capture token id=:id.
        - `rewrites` object[]: Rewrite and proxy rules: the URL stays, the content comes from the destination. _redirects rules match first, then redirects.
          - `source` string, required: Request path to match. * is a splat, :name captures a segment.
          - `destination` string, required: Path to serve under this URL, or an absolute URL to proxy. :splat and :name from the source are substituted.
          - `cache` 'shared': Let shared caches store the proxy response. Absolute-URL destinations only.
          - `force` boolean: Answer even when the request path resolves to a committed file, the ! of a _redirects rule.
          - `query` object: Query parameters the request must carry, as parameter name to capture name: { "id": "id" } is the name=:capture token id=:id.
          - `notFound` boolean: Serve the destination with status 404, the 404 of a _redirects rule. The destination must be a path.
        - `headers` object[]: Response headers to set or remove on matching requests. A _headers rule wins on the same header name.
          - `source` string, required: Request path to match.
          - `headers` union[], required
            - union
              - …
        - `users` object
          - `enabled` boolean, required
          - `providers` object, required
            - `google` union, required
              - …
            - `gravatar` object, required
              - …
            - `spacefast` object, required
              - …
        - `dataSources` object: Named public WordPress sources exposed to repository builds; at most 32 entries.
      - `grandfatherBrandingRemoval` boolean: Whether this Space can keep removing the badge under a newer plan.
      - `settingsDigest` string, required: CAS token for versioned settings writes (digest over title + config overlay). Send it back as baseSettingsDigest on PATCH to get compare-and-swap semantics.
      - `noindex` boolean, required: When true, the live production hostnames serve platform noindex directives. Immutable version and preview hostnames are always noindex regardless of this setting.
      - `pinnedAt` string, date-time, nullable, required: Instant the space was pinned to the top of its team's space list, or null when it is not pinned. The pin is team-wide: everyone who can see the team sees it.
      - `labelIds` string[], required: Ids of the team labels on this space, ordered by label name. Empty when the space carries none. Manage them with PUT and DELETE /v1/spaces/{spaceId}/labels/{labelId}.
      - `viewerCanDelete` boolean: Whether the caller's account may delete this space. Team owners and admins can delete any space in the team; a member can delete the spaces they created. Absent on unclaimed spaces, which their space key governs, and when the request carries no account credential.
      - `viewerCanTransfer` boolean: Whether the caller's account may transfer this space to another team. Team owners and admins can; a member who created the space can from the dashboard while nobody else has published to it and it has no custom domain, database, or paid resource. Present on single-space GET reads only; absent on lists, on write responses, on unclaimed spaces, and when the request carries no account credential.
      - `git` object, nullable, required: Git remote for this space, or null when it has no repository yet. Push to `remoteUrl` to publish.
        - `managedBy` 'spacefast' | 'github' | 'connected', required: Who owns the Git history. `spacefast`: push to publish. `github` or `connected`: deploys from an upstream repository; direct pushes are refused.
        - `remoteUrl` string, nullable, required: Credential-free git remote to push to, or null for an upstream-managed repository. Authenticate as HTTP Basic user `t` with a space key or API key as the password.
        - `repository` string, nullable, required: Name of the connected upstream repository this Space deploys from, else null.
        - `defaultBranch` string, nullable, required: Branch that publishes to the live channel when pushed.
        - `provisioned` boolean, required: Whether the repository behind this block exists yet. Always true for a GitHub binding; for a hosted remote, true once it was minted or first pushed to, and false while there is nothing to browse.
      - `operation` object, nullable, required
        - `id` string, required
        - `kind` string, required
        - `status` 'queued' | 'running' | 'succeeded' | 'failed' | 'canceled', required
        - `resources` object[], required
          - `type` string, required
          - `id` string, required
        - `progress` object
          - `total` integer, required
          - `completed` integer, required
          - `failed` integer, required
        - `diagnostics` object[]
          - `code` string, required: Stable snake_case diagnostic code naming the public contract that produced it.
          - `severity` 'info' | 'warning' | 'error', required: How actionable the diagnostic is.
          - `message` string, required: Human-readable explanation with enough detail to act on.
          - `path` string, nullable: Artifact path the diagnostic points at, for example "_headers:12", when one exists.
          - `provider` 'infra' | 'dns' | 'registrar' | 'runtime', nullable: Upstream system the diagnostic originated from, when not Spacefast itself.
          - `details` object, nullable: Machine-readable context for the diagnostic code.
          - `fix` string, nullable: Concrete, agent-actionable remediation hint, when one can be derived.
          - `retryable` boolean, nullable: Whether retrying the same operation can resolve this diagnostic without the caller changing anything.
        - `createdAt` string, date-time, required
        - `finishedAt` string, date-time
      - `createdAt` string, date-time, required
      - `updatedAt` string, date-time, required
    - `access` object, required
      - `url` string, uri, required
      - `token` string, required
      - `expiresAt` string, date-time, nullable, required
    - `claim` object
      - `key` string, required: The space key (sfc_…): the one credential for this unclaimed space. Bearer auth for publish, update, status, sharing, rotation, and the one-time continuation exchange. Returned only at creation and rotation; save it immediately.
      - `url` string, uri, required: The site door: the live URL with the space key in /__/<key> form. Opening it exchanges the key for a private view session and lands on the site. It is the same key in URL form, so share it as carefully as the key.
      - `claimUrl` string, uri, required: Claim page link in /claim#<key> form. The fragment is the key; browsers never send it to a server and the claim page strips it before analytics. Works until expiresAt and can be opened more than once.
      - `expiresAt` string, date-time, required

## Other responses

- `default`: Problem details (RFC 9457). Any 4xx/5xx response is one `application/problem+json` document.

---

[API](https://skmtc.dev/spacefast/apis/spacefast-api.md) · [All operations](https://skmtc.dev/spacefast/apis/spacefast-api/llms.txt) · [OpenAPI document](https://skmtc.dev/spacefast/apis/spacefast-api/revisions/bd165bc7c983?raw)
