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

# Create a presigned upload ticket

> Server picks single (one PUT) or multipart (one PUT per part) based on size.



## OpenAPI

````yaml /api-reference/openapi.json post /documents/upload-url
openapi: 3.0.3
info:
  title: FileFeed API
  version: '2026-05-25'
  description: >-
    Official FileFeed REST API for connections, pipelines, schemas, pipeline
    runs, webhooks, outbound uploads, documents, files, and notifications.
    Date-based API versioning is controlled by the `FileFeed-Version` request
    header (default `2024-09-01`; latest `2026-05-25`); this document describes
    the `2026-05-25` shape.
servers:
  - url: https://api.sftpsync.io
security:
  - ApiKeyAuth: []
tags:
  - name: Connections
  - name: Pipelines
  - name: Schemas
  - name: Pipeline Runs
  - name: Webhooks
  - name: Outbound Uploads
  - name: Documents
  - name: Files
  - name: Notifications
  - name: Clients (deprecated)
paths:
  /documents/upload-url:
    post:
      tags:
        - Documents
      summary: Create a presigned upload ticket
      description: >-
        Server picks single (one PUT) or multipart (one PUT per part) based on
        size.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUploadTicketParams'
      responses:
        '200':
          description: Upload ticket
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UploadTicket'
        '403':
          $ref: '#/components/responses/Forbidden'
components:
  schemas:
    CreateUploadTicketParams:
      type: object
      properties:
        connectionId:
          type: string
        path:
          type: string
          description: Destination folder relative to the connection root (empty = root).
        filename:
          type: string
        contentType:
          type: string
        size:
          type: integer
          description: File size in bytes (decides single vs multipart).
        force:
          type: boolean
      required:
        - connectionId
        - filename
        - size
    UploadTicket:
      type: object
      description: >-
        Presigned upload ticket. mode=single → PUT the whole file to url;
        mode=multipart → PUT each part to parts[].url then complete with
        uploadId + ETags.
      properties:
        mode:
          type: string
          enum:
            - single
            - multipart
        path:
          type: string
        url:
          type: string
          format: uri
        headers:
          type: object
          additionalProperties:
            type: string
        uploadId:
          type: string
        parts:
          type: array
          items:
            $ref: '#/components/schemas/UploadPartUrl'
        partSize:
          type: integer
      required:
        - mode
        - path
    UploadPartUrl:
      type: object
      properties:
        partNumber:
          type: integer
        url:
          type: string
          format: uri
      required:
        - partNumber
        - url
    ErrorResponse:
      type: object
      properties:
        message:
          type: string
        statusCode:
          type: integer
        error:
          type: string
  responses:
    Forbidden:
      description: Forbidden — e.g. a protected pipeline folder without admin + force.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

````