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

# Get a presigned URL for a direct file upload

> First step of the direct file-upload flow. Issues a presigned S3 POST
policy and records a pending upload.

**Uploading a file takes three steps:**

1. **Get a URL** — call this endpoint. It returns `{ fileId, url, fields }`.
2. **Upload directly to S3** — send a `multipart/form-data` `POST` to
   `url`. Include **every** key/value from `fields` as form fields first,
   then the file itself as the last field named `file`. The upload goes
   straight to S3; it does not pass through this API. A successful upload
   returns HTTP `204` from S3.
3. **Mark the upload complete** — call
   `POST /api/files/upload-complete` with the `fileId` from step 1. This
   records the file and returns its download URL.

The presigned policy enforces the content type and a 1 byte–50 MB size
range. Both `extension` and `contentType` must be on the accepted lists.

`attachEntityType` is `channel`, `aptlet`, or `knowledge`, and
`attachEntityId` is the channel id, aptlet uuid, or knowledge doc id
respectively. The target must exist (scoped to your company) or the
request is rejected. The file is stored under that entity's folder.




## OpenAPI

````yaml /openapi.yaml post /api/files/upload-url
openapi: 3.0.3
info:
  title: Aptly API
  version: '1.0'
  description: >
    The Aptly API lets you read and write cards on any Aptly board from external
    systems.


    All requests require an API key passed as the `x-token` header.

    API keys are scoped to your company and work across all boards.
servers:
  - url: https://core-api.getaptly.com
    description: Production
security:
  - ApiKeyHeader: []
paths:
  /api/files/upload-url:
    post:
      tags:
        - Files
      summary: Get a presigned URL for a direct file upload
      description: >
        First step of the direct file-upload flow. Issues a presigned S3 POST

        policy and records a pending upload.


        **Uploading a file takes three steps:**


        1. **Get a URL** — call this endpoint. It returns `{ fileId, url, fields
        }`.

        2. **Upload directly to S3** — send a `multipart/form-data` `POST` to
           `url`. Include **every** key/value from `fields` as form fields first,
           then the file itself as the last field named `file`. The upload goes
           straight to S3; it does not pass through this API. A successful upload
           returns HTTP `204` from S3.
        3. **Mark the upload complete** — call
           `POST /api/files/upload-complete` with the `fileId` from step 1. This
           records the file and returns its download URL.

        The presigned policy enforces the content type and a 1 byte–50 MB size

        range. Both `extension` and `contentType` must be on the accepted lists.


        `attachEntityType` is `channel`, `aptlet`, or `knowledge`, and

        `attachEntityId` is the channel id, aptlet uuid, or knowledge doc id

        respectively. The target must exist (scoped to your company) or the

        request is rejected. The file is stored under that entity's folder.
      operationId: getFileUploadUrl
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
                - extension
                - size
                - contentType
                - attachEntityType
                - attachEntityId
              properties:
                name:
                  type: string
                  description: Original file name.
                  example: invoice.pdf
                extension:
                  type: string
                  description: >-
                    File extension (lowercase, no dot). Must be an accepted
                    extension.
                  example: pdf
                size:
                  type: integer
                  description: File size in bytes. Must be 1–52428800 (50 MB).
                  example: 20480
                contentType:
                  type: string
                  description: MIME type. Must be an accepted content type.
                  example: application/pdf
                attachEntityType:
                  type: string
                  enum:
                    - channel
                    - aptlet
                    - knowledge
                  description: The kind of entity the file is attached to.
                  example: channel
                attachEntityId:
                  type: string
                  description: >-
                    The channel id (`channel`), aptlet uuid (`aptlet`), or
                    knowledge doc id (`knowledge`) the file belongs to. Must
                    exist within your company.
                  example: 7f3c2a1b9d4e5f6a7b8c9d0e
      responses:
        '200':
          description: Presigned upload policy.
          content:
            application/json:
              schema:
                type: object
                properties:
                  fileId:
                    type: string
                    description: ID to pass to `/api/files/upload-complete`.
                  url:
                    type: string
                    description: S3 endpoint to POST the multipart form to.
                  fields:
                    type: object
                    additionalProperties:
                      type: string
                    description: >-
                      Form fields that must be included in the multipart POST
                      (the file part goes last).
        '400':
          description: Invalid or unsupported file, or missing required field.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Invalid or missing credential.
        '404':
          description: Target channel, aptlet, or knowledge doc not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - ApiKeyHeader: []
        - DelegateToken: []
        - PartnerBearer: []
components:
  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
        message:
          type: string
  securitySchemes:
    ApiKeyHeader:
      type: apiKey
      in: header
      name: x-token
    DelegateToken:
      type: apiKey
      in: header
      name: Authorization
      description: 'Delegate token issued by the platform. Format: `DelegateToken <token>`'
    PartnerBearer:
      type: http
      scheme: bearer
      description: 'Partner token. Format: `Authorization: Bearer <token>`'

````