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

# Get Upload Strategy (Direct or Presigned URL)

> Returns the upload strategy for the requested object.
Local storage always returns direct upload endpoints. S3 storage may return either `presigned` or `direct` strategies depending on the `S3_USE_PRESIGNED_URLS` configuration.
Clients must determine the upload flow from the returned response, using the method field, rather than assuming behavior based on the configured storage backend. 

The filename is used verbatim as the object key. Uploading to an existing key replaces the current object in place. To upload with a server-generated unique key instead, use `POST /api/storage/buckets/{bucketName}/objects`. End-user creates and replacements are gated by the `storage.objects` row-level-security policies.




## OpenAPI

````yaml https://raw.githubusercontent.com/InsForge/InsForge/main/openapi/storage.yaml post /api/storage/buckets/{bucketName}/upload-strategy
openapi: 3.0.3
info:
  title: Insforge Storage API
  version: 2.0.0
  description: Bucket-based storage system similar to S3
servers: []
security: []
paths:
  /api/storage/buckets/{bucketName}/upload-strategy:
    post:
      tags:
        - Client
      summary: Get Upload Strategy (Direct or Presigned URL)
      description: >
        Returns the upload strategy for the requested object.

        Local storage always returns direct upload endpoints. S3 storage may
        return either `presigned` or `direct` strategies depending on the
        `S3_USE_PRESIGNED_URLS` configuration.

        Clients must determine the upload flow from the returned response, using
        the method field, rather than assuming behavior based on the configured
        storage backend. 


        The filename is used verbatim as the object key. Uploading to an
        existing key replaces the current object in place. To upload with a
        server-generated unique key instead, use `POST
        /api/storage/buckets/{bucketName}/objects`. End-user creates and
        replacements are gated by the `storage.objects` row-level-security
        policies.
      parameters:
        - name: bucketName
          in: path
          required: true
          schema:
            type: string
            pattern: ^[a-zA-Z0-9_-]+$
          example: avatars
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - filename
              properties:
                filename:
                  type: string
                  description: Object key to upload to (used verbatim)
                  example: profile-photo.jpg
                contentType:
                  type: string
                  example: image/jpeg
                  description: MIME type of the file
                size:
                  type: integer
                  description: File size in bytes
                  example: 102400
      responses:
        '200':
          description: Upload strategy details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UploadStrategy'
              examples:
                s3:
                  summary: S3 Backend Response
                  value:
                    method: presigned
                    uploadUrl: https://s3-bucket.amazonaws.com/
                    fields:
                      bucket: my-s3-bucket
                      key: app-key/avatars/profile-photo.jpg
                      X-Amz-Algorithm: AWS4-HMAC-SHA256
                      X-Amz-Credential: AKIA.../20250905/us-east-2/s3/aws4_request
                      X-Amz-Date: 20250905T000000Z
                      Policy: eyJ...
                      X-Amz-Signature: abc123...
                    key: profile-photo.jpg
                    confirmRequired: true
                    confirmUrl: >-
                      /api/storage/buckets/avatars/objects/profile-photo.jpg/confirm-upload
                    expiresAt: '2025-09-05T01:00:00Z'
                s3Proxy:
                  summary: S3 Backend (Proxy Mode)
                  value:
                    method: direct
                    uploadUrl: /api/storage/buckets/avatars/objects/profile-photo.jpg
                    key: profile-photo.jpg
                    confirmRequired: false
                local:
                  summary: Local Storage Response
                  value:
                    method: direct
                    uploadUrl: /api/storage/buckets/avatars/objects/profile-photo.jpg
                    key: profile-photo.jpg
                    confirmRequired: false
        '403':
          description: The caller is not permitted to create or replace this object
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error: STORAGE_PERMISSION_DENIED
                message: >-
                  You do not have permission to replace "profile-photo.jpg" in
                  bucket "avatars"
                statusCode: 403
        '404':
          description: Bucket not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - apiKey: []
components:
  schemas:
    UploadStrategy:
      type: object
      required:
        - method
        - uploadUrl
        - key
        - confirmRequired
      properties:
        method:
          type: string
          enum:
            - presigned
            - direct
          description: >-
            Upload method. `presigned` is returned when S3 presigned URLs are
            enabled; `direct` is returned for local storage and S3 proxy mode.
          example: presigned
        uploadUrl:
          type: string
          description: URL to upload the file to
          example: https://s3-bucket.amazonaws.com/
        fields:
          type: object
          description: Form fields for presigned POST (S3 only)
          additionalProperties: true
          example:
            bucket: my-s3-bucket
            key: app-key/avatars/profile.jpg
            X-Amz-Algorithm: AWS4-HMAC-SHA256
        key:
          type: string
          description: Final logical object key (the filename, used verbatim).
          example: profile-photo.jpg
        confirmRequired:
          type: boolean
          description: >-
            Whether the upload must be confirmed after completion. When `false`,
            clients must not call the confirm upload endpoint.
          example: true
        confirmUrl:
          type: string
          description: >-
            Upload confirmation endpoint. Present only when `confirmRequired` is
            `true`.
          example: /api/storage/buckets/avatars/objects/profile.jpg/confirm-upload
        expiresAt:
          type: string
          format: date-time
          description: Expiration time for presigned URL (S3 only)
          example: '2025-09-05T01:00:00Z'
    ErrorResponse:
      type: object
      required:
        - error
        - message
        - statusCode
      properties:
        error:
          type: string
          description: Error code for programmatic handling
          example: VALIDATION_ERROR
        message:
          type: string
          description: Human-readable error message
          example: Invalid request
        statusCode:
          type: integer
          description: HTTP status code
          example: 400
        nextActions:
          type: string
          description: Suggested action to resolve the error
          example: Check your request parameters
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key

````