# Step Function — Upload & Download

Use these step functions for actions that transfer files to or from the provider.

| Function | Use when |
| :--- | :--- |
| `upload_file` | Provider endpoint accepts `multipart/form-data` file uploads |
| `download_file` | Provider endpoint returns binary or file content |

**⚠️ If the provider accepts file content as a base64 string or any other normal body/query parameter — use `step-function-request` instead. `upload_file` is only for `multipart/form-data`.**

**For args configuration — read `references/args-config.md`.**

---

## `upload_file` — Multipart File Upload

### Structure

```yaml
steps:
  - stepId: upload_file
    description: Upload file via multipart form-data
    stepFunction:
      functionName: upload_file
      parameters:
        url: /files
        method: post
        file:
          fieldName: file               # multipart form field name the provider expects
          content: $.inputs.file_content   # base64-encoded file content from inputs
          filename: $.inputs.file_name     # original filename sent as part of form-data
        args:
          - name: folder_id
            value: $.inputs.folder_id
            in: query
```

### Parameters

| Field | Required | Notes |
| :--- | :--- | :--- |
| `url` | Yes | Upload endpoint path |
| `method` | Yes | Usually `post` |
| `file.fieldName` | Yes | Form field name the provider expects for the file |
| `file.content` | Yes | JSONPath to base64-encoded file content — `$.inputs.file_content` |
| `file.filename` | Yes | JSONPath to filename — `$.inputs.file_name` |
| `additionalFields` | No | Extra form fields sent alongside the file |
| `args` | No | Query or header parameters |
| `baseUrl` | No | Override connector baseUrl |
| `authorization` | No | Override authentication |

### Example — Basic Upload

```yaml
- actionId: upload_document
  label: Upload Document
  categories:
    - documents
  actionType: custom
  description: Upload a document to a folder
  details: Uploads a file to the specified folder using multipart form-data. Returns the created file object with its ID and metadata.
  tags:
    - Documents
  resources: PROVIDER_DOCS_URL/docs/files#upload
  inputs:
    - name: folder_id
      description: Target folder ID
      type: string
      in: path
      required: true
    - name: file_content
      description: Base64-encoded file content
      type: string
      in: body
      required: true
    - name: file_name
      description: File name with extension
      type: string
      in: body
      required: true
    - name: name
      description: Custom display name for the file
      type: string
      in: query
      required: false
  steps:
    - stepId: upload_file
      description: Upload file to folder
      stepFunction:
        functionName: upload_file
        parameters:
          url: /folders/${inputs.folder_id}/files
          method: post
          file:
            fieldName: file
            content: $.inputs.file_content
            filename: $.inputs.file_name
          args:
            - name: name
              value: $.inputs.name
              in: query
              condition: '{{present(inputs.name)}}'
  result:
    data: $.steps.upload_file.output.data
```

### Example — Upload with Additional Form Fields

```yaml
steps:
  - stepId: upload_attachment
    description: Upload attachment for a candidate
    stepFunction:
      functionName: upload_file
      parameters:
        url: /candidates/${inputs.candidateId}/attachments
        method: post
        file:
          fieldName: file
          content: $.inputs.file_content
          filename: $.inputs.file_name
        additionalFields:           # extra form fields sent alongside the file
          - name: attachmentType
            value: $.inputs.attachmentType
        args:
          - name: X-API-Key
            value: $.credentials.apiKey
            in: headers
            condition: '{{present(credentials.apiKey)}}'
```

---

## `download_file` — File Download

### Structure

```yaml
steps:
  - stepId: download_file
    description: Download file content
    stepFunction:
      functionName: download_file
      parameters:
        url: /files/${inputs.fileId}/content
        method: get
```

### Parameters

| Field | Required | Notes |
| :--- | :--- | :--- |
| `url` | Yes | Download endpoint path |
| `method` | Yes | Usually `get` |
| `followRedirects` | No | `true` to follow redirect responses |
| `responseMode` | No | `stream` for streaming responses |
| `responseType` | No | `arraybuffer` for binary data |
| `encoding` | No | `base64` or `binary` — how response content is encoded |
| `args` | No | Query or header parameters |
| `baseUrl` | No | Override connector baseUrl |
| `authorization` | No | Override authentication |

### Example — Basic Download

```yaml
- actionId: download_document
  label: Download Document
  categories:
    - documents
  actionType: custom
  description: Download document content by ID
  details: Downloads the binary content of the specified file. Returns the file content as a base64-encoded string.
  tags:
    - Documents
  resources: PROVIDER_DOCS_URL/docs/files#download
  inputs:
    - name: file_id
      description: Unique identifier of the file to download
      type: string
      in: path
      required: true
  steps:
    - stepId: download_file
      description: Download file content
      stepFunction:
        functionName: download_file
        parameters:
          url: /files/${inputs.file_id}/content
          method: get
          followRedirects: true
          responseMode: stream
          encoding: binary
  result:
    data: $.steps.download_file.output.data
```

### Example — Download with ArrayBuffer Encoding

```yaml
steps:
  - stepId: download_report
    description: Download report as PowerPoint
    stepFunction:
      functionName: download_file
      parameters:
        url: /reports/${inputs.reportId}/export
        method: get
        responseType: arraybuffer
        encoding: base64
        args:
          - name: Authorization
            value: $.credentials.accessToken
            in: headers
          - name: format
            value: $.inputs.format
            in: query
            condition: '{{present(inputs.format)}}'
```

---

## Critical Rules

- ✅ Always include step `description`
- ✅ `stepId` must match the reference in `result:\n  data: $.steps.{stepId}.output.data`
- ✅ For `upload_file`: always provide `file.fieldName`, `file.content`, and `file.filename`
- ✅ For `download_file`: set `encoding` to match what the provider returns (`binary` or `base64`)
- ✅ Use `followRedirects: true` if the provider redirects to a CDN or signed URL
- ❌ Never use more than one step per action
- ❌ Do not use `upload_file` for base64-encoded binary payloads — use `request` with body args instead
