---
title: "Start a new version upload"
method: POST
path: "/v1/spaces/{spaceId}/versions"
tags: ["Versions"]
---

# Start a new version upload

`POST /v1/spaces/{spaceId}/versions`

## Request

- Base URL: `https://api.spacefast.com`
- URL: `https://api.spacefast.com/v1/spaces/{spaceId}/versions`
- Auth: one of:
  - HTTP bearer
  - HTTP bearer

Creates a version and returns upload instructions. The declared file manifest drives change-only uploads: unchanged files are retained from the previous version and only the remainder is requested.

## Path parameters

- `spaceId` string, required

## Request body

- object
  - `source` object: Publish provenance recorded on the version; defaults to {kind: "direct_upload"}.
    - `kind` 'direct_upload' | 'cli' | 'dashboard' | 'api' | 'git' | 'import' | 'agent' | 'build' | 'variable_update' | 'config_update', required: How this version was produced.
    - `client` string: Publishing client attribution, for example `spacefast-cli/1.2.3`.
    - `branch` string: Git branch the publish came from.
    - `commit` string: Git commit SHA the publish came from.
    - `message` string: Plain-language description of the publish (the version changelog entry, commit message, or release note). This is THE spelling for the publish description; the version files-diff API is the fallback when none is given.
    - `dirty` boolean: Whether the working tree had uncommitted changes at publish time.
    - `metadata` object: Additional provenance (repository, CI run URL, workflow, actor, ...).
    - `git` object
      - `repository` string, nullable
      - `repositoryFullName` string, nullable
      - `repositoryUrl` string, nullable
      - `ref` string, nullable
      - `branch` string, nullable
      - `branchAliasUrl` string, nullable
      - `commit` string, nullable
      - `commitSha` string, nullable
      - `pullRequestNumber` number, nullable
  - `publishMode` 'additive' | 'snapshot': How to interpret omitted paths in `files`: `additive` retains existing paths unless explicitly replaced; `snapshot` treats `files` as the complete desired manifest.
  - `sourceMetadata` object: Additional control-plane-only provenance for build and deploy read models.
  - `buildLog` string: Build transcript truncated to a bounded size for deploys that ran a local build before publishing.
  - `finalize` object: Finalize intent for a declared upload. The version finalizes itself once Spacefast confirms every declared file landed: at create when nothing needs uploading, otherwise on the `uploads/refresh` call that finds nothing pending. Call refresh after the last upload. The explicit finalize call remains available for recovery and replay.
    - `channel` 'live' | 'production', nullable
  - `files` object[], required: The complete desired file manifest. `sha256` is optional: omit it to upload by path and let the runtime hash the bytes, or include it to upload by content address, with the digest verified as the bytes land. A `sourceUrl` entry is fetched and hashed by the runtime.
    - `path` string, required: Version-relative POSIX path. Canonicalized at intake to UTF-8 NFC, percent-decoded exactly once; max 1,024 bytes in canonical form.
    - `size` integer, required: File size in bytes.
    - `sha256` string: Optional SHA-256 content digest, 64 lowercase hex characters without the `sha256:` prefix. Omit it to let the runtime hash uploaded bytes; include it to upload by content address, with the digest verified as the bytes land.
    - `contentType` string: Optional content type for serving metadata.
    - `sourceUrl` string, uri: Optional HTTPS URL the runtime can fetch directly for this file instead of receiving bytes from the client.
  - `configOnly` boolean: Recompile the configuration on top of the current ready artifact without replacing content: the file catalog carries forward, Functions/Zero declarations and runtime detection are preserved, and the version records a `config_update` source. `files` may name only `sf.jsonc` (the shipped configuration); every other path keeps the current version's bytes. Requires an existing ready version to carry forward. Runtime changes still need a normal content publish.
  - `deletePaths` string[]: Explicit paths to remove when `publishMode` is additive. Omitted paths are retained. Only listed paths are deleted.
  - `immutableAssetPrefixes` string[]: Publisher-owned directory prefixes whose declared files are immutable generation assets. Snapshot publishes retain the matching files from the current generation for exactly one subsequent generation.

## Response `200`

Response for status 200

- 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
    - `ignoredPaths` string[]: Deprecated; current servers return an empty array.
    - `versionId` string, nullable, required: Created version id, or null when the manifest matched and nothing changed.
    - `upload` object, nullable, required: Runtime upload session; present only while bytes still need uploading. Upload first, then finalize.
      - `id` string, required: Upload session id (upl_…) minted by the runtime.
      - `mode` 'dist' | 'source', required: `dist` bytes are publishable output. `source` bytes must be transformed, unpacked, or built before publish.
      - `expiresAt` string, date-time, required: Instant when the session token expires. This rotates only the token, never the version lifecycle boundary. Resume always mints a fresh token.
      - `summary` object, required: Counts for the whole manifest, independent of target paging.
        - `upload` integer, required: Files that still need uploading.
        - `reused` integer, required: Files satisfied by hash reuse.
        - `ignored` integer: Deprecated; current servers return zero.
      - `targets` object[], required: Opaque upload targets, bounded by the instruction payload budget. Upload these, then call `links.refresh` for the remainder.
        - `path` string, required: Caller-local path/key identifying the bytes this target accepts.
        - `method` 'PUT' | 'POST', required: HTTP method to use for this target.
        - `url` union, required: Absolute or API-relative upload URL issued by the control plane.
          - string, uri
          - string
        - `headers` object, required: Exact headers to send with the upload request.
        - `body` object: Optional body recipe. Omitted means the client uploads the local bytes for `path`; `url` means POST the URL for server-side fetch.
          - `kind` 'url', required
          - `url` string, uri, required
        - `size` integer: Expected byte size when known.
        - `maxBytes` integer: Maximum accepted byte size when the server can advertise it.
        - `sha256` string
        - `contentType` string
      - `bulk` object: Optional direct runtime transport for this page's content-addressed targets. Clients that do not support it continue with targets.
        - `kind` 'zip-cas-v1', required
        - `method` 'PUT', required
        - `url` union, required: Upload-auth runtime URL that accepts a ZIP of SHA-named CAS blobs.
          - string, uri
          - string
        - `headers` object, required: Exact headers to send with the bulk upload request.
        - `maxCompressedBytes` integer, required
        - `maxExpandedBytes` integer, required
        - `maxBlobs` integer, required
      - `links` object, required
        - `refresh` string, required
        - `resume` string
        - `finalize` string, required
      - `details` object
        - `reused` object[]
          - `path` string, required
          - `reason` string, 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.

## Other responses

- `201`: Response for status 201
- `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)
