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

# Renew an upload session

> Mints a fresh create-only (`ifGenerationMatch=0`) GCS resumable session URL for an existing permanent-bucket (`deidBypassed`) `uploading` sample in the calling organization that has no jobs or bound object generation, preserving the sample ID, object path, declared file size, content hash, and MPP snapshot. Replays the caller-supplied `contentType` recorded on new uploads, or infers the canonical WSI MIME type from `filename` on historical rows where `contentType` was not persisted. Prechecks permanent-bucket storage metadata and reconciles an already-finalized object before returning `409`; quarantine uploads are rejected with a non-retryable `409` (`reason: "quarantine_renewal_unsupported"`) without minting a session. Use this only when the prior `uploadUrl` was lost before completion or expired after GCS's 7-day resumable session TTL; when a known `uploadUrl` returns `308 Resume Incomplete`, resume from its acknowledged byte offset instead. Stream the full declared bytes starting from byte offset `0` to the new `uploadUrl`, then poll `GET /uploads/{id}` until the sample leaves `uploading`.



## OpenAPI

````yaml POST /uploads/{id}
openapi: 3.1.0
info:
  title: Strand AI Platform API
  version: v1
  description: >-
    REST surface for uploading WSIs, submitting Lattice inference jobs, and
    streaming results. All endpoints require an API key or Strand AI OAuth
    access token in the `Authorization: Bearer` header.
servers:
  - url: https://app.strandai.com/api/v1
    description: Production
security:
  - ApiKey: []
  - OAuth2: []
paths:
  /uploads/{id}:
    post:
      summary: Renew a resumable upload session
      description: >-
        Mints a fresh create-only (`ifGenerationMatch=0`) GCS resumable session
        URL for an existing permanent-bucket (`deidBypassed`) `uploading` sample
        in the calling organization that has no jobs or bound object generation,
        preserving the sample ID, object path, declared file size, content hash,
        and MPP snapshot. Replays the caller-supplied `contentType` recorded on
        new uploads, or infers the canonical WSI MIME type from `filename` on
        historical rows where `contentType` was not persisted. Prechecks
        permanent-bucket storage metadata and reconciles an already-finalized
        object before returning `409`; quarantine uploads are rejected with a
        non-retryable `409` (`reason: "quarantine_renewal_unsupported"`) without
        minting a session. Use this only when the prior `uploadUrl` was lost
        before completion or expired after GCS's 7-day resumable session TTL;
        when a known `uploadUrl` returns `308 Resume Incomplete`, resume from
        its acknowledged byte offset instead. Stream the full declared bytes
        starting from byte offset `0` to the new `uploadUrl`, then poll `GET
        /uploads/{id}` until the sample leaves `uploading`.
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Renewed resumable upload URL
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UploadSessionRenewed'
        '400':
          description: Invalid request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: Upload not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >-
            Upload is a quarantine upload (`reason:
            "quarantine_renewal_unsupported"`), is not in an unfinalized
            `uploading` state, already has jobs, or has an object finalized in
            storage
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '413':
          description: Request body exceeds maximum size
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    UploadSessionRenewed:
      type: object
      additionalProperties: false
      required:
        - id
        - uploadId
        - uploadUrl
        - gcsPath
        - filename
        - fileSize
        - status
        - existing
      properties:
        id:
          type: string
          format: uuid
        uploadId:
          type: string
          format: uuid
        uploadUrl:
          type: string
          description: >-
            Fresh create-only (`ifGenerationMatch=0`) GCS resumable upload URL.
            Stream the full declared bytes starting from byte offset `0`.
        gcsPath:
          type: string
        filename:
          type: string
        fileSize:
          type: string
          description: bytes, stringified bigint
        status:
          type: string
          enum:
            - uploading
        createdAt:
          type: string
          format: date-time
          nullable: true
        widthPx:
          type: integer
          nullable: true
        heightPx:
          type: integer
          nullable: true
        autoSegment:
          type: boolean
        existing:
          type: boolean
          enum:
            - false
    Error:
      type: object
      required:
        - error
        - message
      properties:
        error:
          type: string
        message:
          type: string
        reason:
          type: string
          nullable: true
        required:
          type: integer
          nullable: true
        retryAfterSeconds:
          type: integer
          nullable: true
  securitySchemes:
    ApiKey:
      type: http
      scheme: bearer
      bearerFormat: sk-strand-XXXXXXXXXXXXXXXXXXXXXXXX
    OAuth2:
      type: oauth2
      description: >-
        Strand AI authorization-code flow with S256 PKCE, explicit organization
        consent, and RFC 8707 resource binding.
      flows:
        authorizationCode:
          authorizationUrl: https://auth.strandai.com/oauth2/auth
          tokenUrl: https://auth.strandai.com/oauth2/token
          scopes:
            samples:read: Read slide metadata and estimates
            samples:write: Upload and change slides
            jobs:read: Read run status
            jobs:write: Start, export, or cancel runs
            results:read: Read and download results
            credits:spend: Reserve and spend organization credits

````

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