> ## Documentation Index
> Fetch the complete documentation index at: https://docs.goosybear.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Import or replace a site from an archive

> Uploads one ZIP archive and either creates a site or replaces the source of an existing one. The service classifies the archive from its CONTENTS — a prebuilt bundle is staged immediately, a supported source project is queued for the build rail — and validates any `pages.deploy.json` it carries against the published `PagesDeployManifest` schema, returning the manifest it resolved on every success. The archive must be no larger than 41943040 bytes.



## OpenAPI

````yaml /openapi.json post /api/pages/ingest
openapi: 3.1.0
info:
  title: Goosy Bear API
  version: 1.0.0-beta
  summary: Manage workspace content, projects, Data tables, Pages, library and credits.
  description: >-
    BETA. This API is in beta: paths, request shapes and response envelopes may
    change, and every response carries an `x-goosy-api: beta` header for as long
    as that is true. Pin the OpenAPI document you generated against and
    re-generate when it changes.
servers:
  - url: https://app.goosybear.ai
    description: Production
security:
  - tenantApiKey: []
paths:
  /api/pages/ingest:
    post:
      tags:
        - pages
      summary: Import or replace a site from an archive
      description: >-
        Uploads one ZIP archive and either creates a site or replaces the source
        of an existing one. The service classifies the archive from its CONTENTS
        — a prebuilt bundle is staged immediately, a supported source project is
        queued for the build rail — and validates any `pages.deploy.json` it
        carries against the published `PagesDeployManifest` schema, returning
        the manifest it resolved on every success. The archive must be no larger
        than 41943040 bytes.
      operationId: ingestPageArchive
      parameters:
        - name: workspace
          in: query
          required: false
          description: >-
            Which workspace to act in — its slug or id. The SAME argument every
            workspace-scoped tool takes, resolved the same way: an account-wide
            key may select any workspace its holder currently reaches, a
            workspace-pinned key may only name its own, and a call that names
            nothing falls through to your default. It is a QUERY parameter
            rather than a body field on purpose: this endpoint's body is a
            multipart upload, and reading a field out of it would decode that
            body before the bearer and the rate limiter had run. With more than
            one reachable workspace and no default, the call is refused as
            `workspace_ambiguous` and the choices are listed. Ignored for a
            signed-in session, whose workspace comes from its own claims.
          schema:
            type: string
            minLength: 1
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              additionalProperties: false
              properties:
                file:
                  type: string
                  format: binary
                  description: The single ZIP archive to import.
                siteId:
                  type: string
                  format: uuid
                  description: >-
                    Replace the source or staged bundle on this existing site.
                    Omit to create one.
                name:
                  type: string
                  description: >-
                    Display name for a NEWLY created site. Ignored when `siteId`
                    is sent.
              required:
                - file
      responses:
        '200':
          description: >-
            The archive was accepted. Read `data.kind` to tell a staged upload
            from a queued build.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                    const: true
                  data:
                    type: object
                    properties:
                      siteId:
                        type: string
                        format: uuid
                        description: The site this upload landed on.
                      siteName:
                        type: string
                      kind:
                        type: string
                        enum:
                          - bundle
                          - prebuilt
                          - source
                        description: >-
                          What the archive turned out to be. `bundle` and
                          `prebuilt` are staged immediately and carry
                          `revision`; `source` is queued for the build rail and
                          carries `buildRunId`.
                      revision:
                        type: string
                        description: 'Present for a staged upload: the revision now staged.'
                      buildRunId:
                        type: string
                        description: >-
                          Present for a source upload: pass it to
                          `page.build_status` as `build_run_id`.
                      objectCount:
                        type: integer
                      pageCount:
                        type: integer
                      bytes:
                        type: integer
                      findings:
                        type: array
                        items:
                          type: object
                          properties:
                            rule:
                              type: string
                            severity:
                              type: string
                            path:
                              type:
                                - string
                                - 'null'
                            message:
                              type: string
                          required:
                            - rule
                            - severity
                            - message
                          additionalProperties: false
                        description: >-
                          Conformance findings. ALWAYS present — an empty array
                          means 'nothing to fix', not 'we did not check'.
                      report:
                        type: object
                        properties:
                          status:
                            type: string
                          kind:
                            type: string
                        required:
                          - status
                          - kind
                        additionalProperties: true
                        description: >-
                          What the importer detected and accepted. Always read
                          it: server routes, unsupported dependencies and unsafe
                          paths surface here.
                      deploySource:
                        type: string
                        enum:
                          - declared
                          - legacy
                          - synthesized
                        description: >-
                          Where the deploy manifest came from — the author's
                          `pages.deploy.json`, a translated legacy
                          `pages.functions.json`, or one we synthesized.
                      deploy:
                        $ref: '#/components/schemas/PagesDeployManifest'
                    required:
                      - bytes
                      - deploy
                      - deploySource
                      - findings
                      - kind
                      - objectCount
                      - pageCount
                      - report
                      - siteId
                      - siteName
                    additionalProperties: false
                required:
                  - ok
                  - data
                additionalProperties: false
        '400':
          description: >-
            The body was not multipart/form-data with a `file` field, the
            archive failed the size or content guards, or its
            `pages.deploy.json` did not match the contract. The refusal names
            the field.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PageIngestError'
        '401':
          description: No bearer credential, or one that did not resolve.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PageIngestError'
        '403':
          description: >-
            Programmatic access is unavailable to this holder, the named
            workspace is outside the key's scope, or the holder lacks
            `pages.manage`. `workspace_ambiguous` and `workspace_unreachable`
            also answer here, and the slugs this key may pass are appended to
            `error.message`.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PageIngestError'
        '404':
          description: The `siteId` is not a site in the resolved workspace.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PageIngestError'
        '429':
          description: >-
            The API key is over its rate limit. Wait for `Retry-After` before
            retrying.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
            Retry-After:
              description: Whole seconds to wait before retrying.
              schema:
                type: integer
                minimum: 1
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PageIngestError'
        '500':
          description: An unexpected server error occurred while handling the import.
          headers:
            x-goosy-api:
              description: Present while this API is in beta; the value is `beta`.
              schema:
                type: string
                const: beta
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PageIngestError'
components:
  schemas:
    PagesDeployManifest:
      type: object
      properties:
        entry:
          type: string
          minLength: 1
          maxLength: 512
          description: >-
            The Worker module that answers `routes`, relative to the bundle
            root. Omit it for a static site.
        assets:
          type: string
          minLength: 1
          maxLength: 512
          description: >-
            The directory holding the site's static files, relative to the
            bundle root.
        routes:
          type: array
          items:
            type: object
            properties:
              pattern:
                type: string
                minLength: 1
                maxLength: 512
                description: >-
                  A site-root-relative path the Worker answers. `*` is allowed
                  only as a trailing `/*`.
            required:
              - pattern
            additionalProperties: false
          description: >-
            Which paths the Worker answers; everything else is served as a
            static file.
        bindings:
          type: object
          properties:
            database:
              type: object
              properties:
                migrations:
                  type: string
                  minLength: 1
                  maxLength: 512
                  description: >-
                    Directory of `.sql` migrations for this site's own database,
                    applied in filename order.
                tables:
                  type: array
                  items:
                    type: string
                    minLength: 1
                    maxLength: 63
                  description: The tables this site's code owns.
                stagedMigrationsPrefix:
                  type: string
                  minLength: 1
                  maxLength: 64
                  description: >-
                    PLATFORM-WRITTEN. Where the migrations above were actually
                    staged, once the bundle was relocated into the reserved
                    prefix. Never write this yourself — a manifest that carries
                    it on upload is refused.
              additionalProperties: false
              description: >-
                The site's own database. Declaring it provisions one on the
                first build.
            projectDatabase:
              type: string
              enum:
                - none
                - read
                - readwrite
              description: >-
                How this site reaches the PROJECT database shared by its
                project's sites. Defaults to `none`.
            secrets:
              type: array
              items:
                type: string
                minLength: 1
                maxLength: 64
              description: >-
                Secret NAMES this Worker reads. Values are set on the site,
                never in this file.
            submissions:
              type: string
              minLength: 1
              maxLength: 63
              description: >-
                A table that platform form posts are also written to, so a
                static site keeps its own entries.
          additionalProperties: false
          description: What this bundle asks to be wired to.
        limits:
          type: object
          properties:
            cpuMs:
              type: integer
              exclusiveMinimum: 0
              description: >-
                CPU milliseconds per invocation. Defaults to 10000; the platform
                ceiling is 30000.
            subRequests:
              type: integer
              exclusiveMinimum: 0
              description: >-
                Outbound sub-requests per invocation. Defaults to 20; the
                platform ceiling is 50.
          additionalProperties: false
          description: >-
            The caps this bundle asks for. The platform decides the ceilings and
            refuses anything over them.
      additionalProperties: false
      description: >-
        `pages.deploy.json` — the one file a bundle uses to say what it is and
        what it needs. Put it at the bundle root.
    PageIngestError:
      type: object
      properties:
        ok:
          type: boolean
          const: false
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
          required:
            - code
            - message
          additionalProperties: false
      required:
        - ok
        - error
      additionalProperties: false
      description: >-
        A Pages import that did not succeed. ⚠️ Unlike a tool refusal, this
        envelope has NO `workspaces` array — on `workspace_ambiguous` and
        `workspace_unreachable` the slugs you may pass are appended to
        `error.message` instead.
  securitySchemes:
    tenantApiKey:
      type: http
      scheme: bearer
      description: >-
        An API key minted at Settings › API & MCP. Send it as `Authorization:
        Bearer <key>`. A key carries its holder's own permissions, resolved on
        every call — revoking a membership closes the key's reach immediately.
        Keep it in an environment variable (`GOOSY_API_KEY`), never in a
        committed file.

````