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

# Open an upload for a deploy's files

> Open an upload for a deploy's files in the app's sandbox, naming the SHA-256 and size of the tar archive (at most 536870912 bytes, 512 MiB) that will be sent.



## OpenAPI

````yaml https://api.ravion.com/openapi.yaml post /apps/{id}/uploads
openapi: 3.0.0
info:
  title: Ravion
  version: 0.0.0
servers:
  - url: https://api.ravion.com
security:
  - BearerAuth: []
tags:
  - name: Projects
  - name: Environments
  - name: FeatureFlags
  - name: Pipelines
  - name: PipelineRuns
  - name: TerraformResources
  - name: TerraformExecutionSummaries
  - name: PipelineStepExecutions
  - name: AwsCloudWatch
  - name: AwsAmp
  - name: PipelineVersions
  - name: Organizations
  - name: Stacks
  - name: StackWorkspaces
  - name: Auth
  - name: OAuth
  - name: User
  - name: Health
  - name: Memberships
  - name: ServiceAccounts
  - name: Integrations
  - name: AwsDefaultNetworks
  - name: AwsAccounts
  - name: ApiKeys
  - name: EksPrometheus
  - name: EksLoki
  - name: ExecutionEnvironments
  - name: ModuleDefinitions
  - name: ModuleCategories
  - name: ModuleVersions
  - name: ModuleInstances
  - name: DefaultValueDefinitions
  - name: DefaultValues
  - name: CodeSources
  - name: Github
  - name: GitHub Actions
  - name: Alerts
  - name: Gitlab
  - name: Slack
  - name: Git
  - name: MergeQueues
  - name: Values
  - name: Deployments
  - name: DeploymentResources
  - name: InfrastructureEvents
  - name: WebSocket
  - name: Domains
  - name: AcmCertificates
  - name: NotificationDestinations
  - name: NotificationDispatches
  - name: NotificationEvents
  - name: NotificationRules
  - name: Activity
  - name: Describe
  - name: Reports
  - name: BillingPlans
  - name: BillingAccounts
  - name: BillingCycles
  - name: BillingUsageSummaries
  - name: BillingAddOns
  - name: BillingInvoices
  - name: Authorization
  - name: Sandboxes
  - name: SandboxCommands
  - name: SandboxPorts
  - name: Apps
paths:
  /apps/{id}/uploads:
    post:
      tags:
        - Apps
      summary: Open an upload for a deploy's files
      description: >-
        Open an upload for a deploy's files in the app's sandbox, naming the
        SHA-256 and size of the tar archive (at most

        536870912 bytes, 512 MiB) that will be sent. Returns 201 with the URL to
        send the files to, the key to seal them to

        and the token to send them with: seal the archive to `recipientKey` and
        `PUT` it (`Content-Type:

        application/octet-stream`) to `url` with `Authorization: Bearer <token>`
        before `expiresAt`. The sealed archive

        goes through the App Cluster's load balancer and router straight to the
        app's sandbox's host, which alone can open

        it; it never passes through Ravion. The host unpacks into a directory of
        the upload's own only the files,

        directories and symbolic links that stay inside it, and only once the
        archive opened whole and matches the SHA-256

        and size it was opened with. One request sends it, and its 200 says the
        archive arrived whole. Then read the upload

        until it is `SUCCEEDED` or `FAILED`, and deploy it by its `uploadId` and
        `archiveSha256`.


        A sandbox has one upload open at a time: opening another closes the one
        before it. You need permission to update

        the app and to create deployments of its App Cluster, as a deploy does.


        Start the app first: fails with 409 `NO_SANDBOX` when the app has no
        sandbox and 409 when its sandbox is not

        `RUNNING`. Fails with 409 `UPLOAD_ROUTER_NOT_CONNECTED` when no instance
        of the App Cluster's router is connected to

        Ravion, and with 422 `UPLOAD_UNSUPPORTED` when the App Cluster's router
        or the sandbox's host runs a release from

        before uploads were sealed to the sandbox's host.
      operationId: CreateAppUpload
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              additionalProperties: false
              properties:
                data:
                  $ref: '#/components/schemas/AppUploadRequest'
              required:
                - data
              type: object
        required: true
      responses:
        '201':
          content:
            application/json:
              schema:
                additionalProperties: false
                properties:
                  data:
                    $ref: '#/components/schemas/AppUpload'
                required:
                  - data
                type: object
          description: >-
            The request has succeeded and a new resource has been created as a
            result.
        '400':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors.UserFacingErrorData'
          description: The request is invalid or malformed.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors.UserFacingErrorData'
          description: You are not authenticated
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors.UserFacingErrorData'
          description: You do not have permission to access this resource.
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors.UserFacingErrorData'
          description: The server cannot find the requested resource.
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors.UserFacingErrorData'
          description: The request conflicts with the current state of the server.
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors.UserFacingErrorData'
          description: Client error
        '500':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Errors.UserFacingErrorData'
          description: Server error
components:
  schemas:
    AppUploadRequest:
      additionalProperties: false
      description: The archive an upload is opened for.
      properties:
        archiveBytes:
          description: Size of the tar archive in bytes, at most 536870912 (512 MiB).
          format: int64
          maximum: 536870912
          minimum: 0
          type: integer
        archiveSha256:
          description: >-
            SHA-256, in lower-case hex, of the tar archive that will be sent.
            The app's sandbox unpacks the files only when the archive it
            receives is exactly this one.
          pattern: ^[0-9a-f]{64}$
          type: string
      required:
        - archiveSha256
        - archiveBytes
      type: object
    AppUpload:
      additionalProperties: false
      description: >-
        An upload opened for a deploy's files: where to send them, the key to
        seal them to and the token to send them with.
      properties:
        expiresAt:
          allOf:
            - $ref: '#/components/schemas/UtcDateTime'
          description: >-
            When the upload expires. The files must be sent before then; an
            upload nobody sent is closed.
        recipientKey:
          description: >-
            Public key the archive is sealed to, as unpadded base64url: an
            X25519 key made by the app's sandbox's host for

            this upload alone, whose private half never leaves that host. Seal
            the tar archive to it with HPKE (RFC 9180):

            DHKEM(X25519, HKDF-SHA256), HKDF-SHA256 and AES-256-GCM, with the
            info `ravion upload v1`, a zero byte and the

            upload's id. Send the 8 bytes `RVNUPLD1` and the 32-byte
            encapsulated key, then the archive in chunks of

            65536 bytes, the last of which may be shorter or empty, each sealed
            in turn under the one context with a

            one-byte associated data of 1 for the last chunk and 0 for the
            others, and each preceded by that byte and the

            sealed chunk's length as 4 bytes big-endian. `ravion deploy` does
            this for you.
          type: string
        token:
          description: >-
            Bearer token that sends the files to `url`, once. It is returned
            only here: Ravion keeps its SHA-256 alone.
          type: string
        uploadId:
          description: >-
            The upload's id, which a deploy names once the files have been
            unpacked.
          type: string
        url:
          description: >-
            Where to send the files: `PUT` the sealed archive here with
            `Authorization: Bearer <token>`. The URL is under the App Cluster's
            domain, and the archive goes through the App Cluster's load balancer
            and router straight to the app's sandbox, never through Ravion.
          type: string
      required:
        - uploadId
        - url
        - recipientKey
        - token
        - expiresAt
      type: object
    Errors.UserFacingErrorData:
      additionalProperties: false
      description: |-
        User-facing error presentation data.
        This is what the API returns to the frontend after formatting ErrorData
        using CEL templates from the error registry.

        Used for both:
        - Error fields on domain models (e.g., PipelineRun.error)
        - API error response bodies (HTTP 4xx/5xx responses)
      properties:
        action:
          allOf:
            - $ref: '#/components/schemas/Errors.Action'
          description: Optional action to help resolve the error
        code:
          description: Full error code, e.g., "Ravion:Pipeline:NOT_FOUND"
          type: string
        description:
          description: Additional description with more details
          type: string
        details:
          description: Structured details rendered as user-facing sections.
          items:
            $ref: '#/components/schemas/Errors.UserFacingErrorDetailSection'
          type: array
        isInternal:
          description: >-
            Indicates whether this error is internal (only set when
            ShowInternal=true).

            This allows SUPERADMINs to identify internal errors while viewing
            full details.
          type: boolean
        message:
          description: Main error message (required)
          type: string
        metadata:
          additionalProperties: {}
          description: >-
            Error params/metadata. Stripped for internal errors unless
            superadmin.
          type: object
        requestId:
          description: Request ID for correlating errors with server logs.
          type: string
      required:
        - code
        - message
      type: object
    UtcDateTime:
      description: UTC RFC3339 timestamp with a required Z suffix
      format: date-time
      pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,9})?Z$
      type: string
      x-go-type: apitypes.UTCDateTime
      x-go-type-import:
        name: apitypes
        path: ravion/api-go/pkg/apitypes
    Errors.Action:
      additionalProperties: false
      description: Action to help user resolve the error
      properties:
        label:
          description: Button/link label text
          type: string
        url:
          description: URL to navigate to for resolution
          type: string
      required:
        - label
        - url
      type: object
    Errors.UserFacingErrorDetailSection:
      additionalProperties: false
      description: Structured user-facing error detail section.
      properties:
        items:
          description: List of detail values for this section.
          items:
            type: string
          type: array
        object:
          additionalProperties: {}
          description: Structured detail payload for object rendering.
          type: object
        render:
          description: Rendering hint for clients. Valid values are list or object.
          type: string
        title:
          description: Detail section title shown in the UI.
          type: string
      required:
        - title
        - render
      type: object
  securitySchemes:
    BearerAuth:
      scheme: Bearer
      type: http

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.