---
title: Workflow Blocks Reference
subtitle: Complete reference for all workflow block types
slug: multi-step-automations/workflow-blocks-reference
---

This page covers all block types available for building workflows.

Blocks are defined in the `workflow_definition.blocks` array. Use JSON when passing a `json_definition` or YAML when passing a `yaml_definition` — both formats are shown for every block below.

---

## Quick reference

| Block Type | Use this to |
|------------|---------|
| [`navigation`](#navigation) | Navigate websites and take actions with a goal |
| [`action`](#action) | Take a single action on the current page |
| [`extraction`](#extraction) | Extract structured data from a page |
| [`login`](#login) | Authenticate using stored credentials |
| [`task`](#task) | Legacy block combining navigation and extraction |
| [`task_v2`](#task-v2) | Simplified task block using natural language prompts |
| [`validation`](#validation) | Assert conditions and control workflow flow |
| [`conditional`](#conditional) | Branch workflow based on conditions |
| [`for_loop`](#for-loop) | Iterate over arrays and repeat nested blocks |
| [`goto_url`](#goto-url) | Navigate directly to a URL |
| [`file_download`](#file-download) | Download files from websites |
| [`file_url_parser`](#file-parser) | Parse CSV, Excel, or PDF files |
| [`pdf_parser`](#pdf-parser) | Parse PDF files specifically (deprecated, use `file_url_parser`) |
| [`download_to_s3`](#download-to-s3) | Download a file from URL to S3 |
| [`upload_to_s3`](#upload-to-s3) | Upload workflow files to S3 |
| [`file_upload`](#file-upload) | Upload files to S3 or Azure storage |
| [`http_request`](#http-request) | Make HTTP API calls |
| [`send_email`](#send-email) | Send emails with attachments |
| [`code`](#code) | Execute custom Python code |
| [`text_prompt`](#text-prompt) | Make LLM calls for text generation |
| [`print_page`](#print-page) | Save current page as PDF |
| [`wait`](#wait) | Pause execution for a duration |
| [`human_interaction`](#human-interaction) | Pause for human approval via email |

---

## Common parameters

These parameters are available on all block types:

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `label` | string | — | **Required.** Unique identifier for this block within the workflow. Used for referencing outputs as `{{label_output}}`. |
| `continue_on_failure` | boolean | `false` | If `true`, workflow continues even if this block fails. |
| `next_loop_on_failure` | boolean | `false` | If `true` and inside a loop, skips to next iteration on failure. |
| `next_block_label` | string | — | Label of the next block to execute. If omitted, uses sequential order. |
| `model` | object | — | Override model configuration for this block. |

### Finally block

You can designate any block as a "finally" block that always executes when the workflow ends — whether it completed, failed, terminated, or timed out. The only exception is explicit cancellation.

Set `finally_block_label` at the workflow definition level (alongside `parameters` and `blocks`):

```yaml
workflow_definition:
  parameters: [...]
  blocks:
    - block_type: navigation
      label: main_task
      # ...
    - block_type: send_email
      label: notify_team
      # ...
  finally_block_label: notify_team
```

The referenced block must be a terminal block — it cannot have a `next_block_label`.

---

### Error code mapping

Several blocks accept an `error_code_mapping` parameter. This is an object mapping custom error codes to natural language descriptions. Skyvern evaluates each description against the current page state and surfaces matching errors in the block output.

```json
{
  "error_code_mapping": {
    "INVALID_CREDENTIALS": "The page shows an error message indicating the username or password is incorrect.",
    "ACCOUNT_LOCKED": "The page indicates the account has been locked or suspended.",
    "CAPTCHA_REQUIRED": "A CAPTCHA challenge is displayed that cannot be solved."
  }
}
```

### Block outputs

Every block produces an output accessible by other blocks as `{{label_output}}`, where `label` is the block's `label` value. The output shape depends on the block type:

- **Navigation / Action / Login / File Download**: the output is `null` on success (the primary effect is the browser state change).
- **Extraction**: the output matches the `data_schema` you provide (or a free-form object if no schema is given).
- **Task**: `null` when only `navigation_goal` is set. When `data_extraction_goal` is set, the output matches the `data_schema`.
- **Code**: the value of the `result` variable at the end of execution.
- **Text Prompt**: the LLM response, structured according to `json_schema` if provided.
- **File Parser / PDF Parser**: the parsed file content (structured if `json_schema` is provided).
- **For Loop**: an array of outputs, one per iteration.
- **HTTP Request**: the response body (as JSON if applicable, otherwise as a string).
- **Upload to S3 / File Upload / Download to S3**: the storage URL of the uploaded/downloaded file.
- **Print Page**: the file path of the saved PDF.
- **Validation / Conditional / Goto URL / Wait / Send Email / Human Interaction**: `null` (control-flow blocks).

---

## Navigation

Navigate through websites to take actions with a natural language goal.

<CodeGroup>
```json JSON
{
  "block_type": "navigation",
  "label": "search_registry",
  "url": "https://asha.org/verify",
  "navigation_goal": "Search for the person using the provided information. COMPLETE when search results are displayed. TERMINATE if no results found.",
  "parameter_keys": ["first_name", "last_name", "employee_state"],
  "engine": "skyvern-2.0",
  "max_steps_per_run": 20
}
```

```yaml YAML
- block_type: navigation
  label: search_registry
  url: "https://asha.org/verify"
  navigation_goal: |
    Search for the person using:
    - First name: {{first_name}}
    - Last name: {{last_name}}
    - State: {{employee_state}}

    COMPLETE when search results are displayed.
    TERMINATE if no results found.
  parameter_keys:
    - first_name
    - last_name
    - employee_state
  engine: skyvern-2.0
  max_steps_per_run: 20
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `navigation_goal` | string | — | **Required.** Natural language description of what to do. Include when to COMPLETE or TERMINATE. |
| `url` | string | — | Starting URL. If omitted, continues from previous block's page. |
| `title` | string | `""` | Display title for this block. |
| `engine` | string | `"skyvern-1.0"` | `"skyvern-1.0"` or `"skyvern-2.0"`. |
| `max_steps_per_run` | integer | — | Maximum steps this block can take. |
| `max_retries` | integer | `0` | Number of retry attempts on failure. |
| `parameter_keys` | array | — | Parameters this block can access. |
| `error_code_mapping` | object | — | Map conditions to custom error codes. |
| `complete_on_download` | boolean | `false` | Complete when a file download is triggered. |
| `download_suffix` | string | — | Filename for the downloaded file. |
| `complete_criterion` | string | — | Natural language condition for completion. |
| `terminate_criterion` | string | — | Natural language condition for termination. |
| `complete_verification` | boolean | `true` | Whether to verify completion criteria. |
| `include_action_history_in_verification` | boolean | `false` | Include action history when verifying completion. |
| `totp_identifier` | string | — | TOTP credential identifier for 2FA. |
| `totp_verification_url` | string | — | URL to fetch TOTP codes. |
| `disable_cache` | boolean | `false` | Disable caching for this block. |

<Info>
For guidance on which engine to choose (`skyvern-1.0` vs `skyvern-2.0`), see [Engine Selection](/running-automations/task-parameters#engine).
</Info>

---

## Action

Take a single action on the current page without navigation.

<CodeGroup>
```json JSON
{
  "block_type": "action",
  "label": "click_download_button",
  "navigation_goal": "Click the \"Download PDF\" button",
  "engine": "skyvern-1.0"
}
```

```yaml YAML
- block_type: action
  label: click_download_button
  navigation_goal: Click the "Download PDF" button
  engine: skyvern-1.0
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `navigation_goal` | string | — | Description of the action to take. |
| `url` | string | — | URL to navigate to first. |
| `title` | string | `""` | Display title for this block. |
| `engine` | string | `"skyvern-1.0"` | AI engine to use (`"skyvern-1.0"` or `"skyvern-2.0"`). |
| `max_retries` | integer | `0` | Number of retry attempts. |
| `parameter_keys` | array | — | Parameters this block can access. |
| `error_code_mapping` | object | — | Map conditions to custom error codes. |
| `complete_on_download` | boolean | `false` | Complete when download triggered. |
| `download_suffix` | string | — | Filename for the downloaded file. |
| `totp_identifier` | string | — | TOTP credential identifier. |
| `totp_verification_url` | string | — | URL to fetch TOTP codes. |
| `disable_cache` | boolean | `false` | Disable caching for this block. |

---

## Extraction

Extract structured data from a page without taking any actions.

<CodeGroup>
```json JSON
{
  "block_type": "extraction",
  "label": "extract_credentials",
  "data_extraction_goal": "Extract the professional credentials including ASHA account number, certification status, and valid through date.",
  "data_schema": {
    "type": "object",
    "properties": {
      "asha_account_number": { "type": "string" },
      "certification_status": { "type": "string" },
      "valid_through": { "type": "string" }
    }
  }
}
```

```yaml YAML
- block_type: extraction
  label: extract_credentials
  data_extraction_goal: |
    Extract the professional credentials:
    - ASHA account number
    - Certification status (active/inactive)
    - Valid through date
    - Supervisor/mentor information
  data_schema:
    type: object
    properties:
      asha_account_number:
        type: string
      certification_status:
        type: string
        enum: ["active", "inactive", "expired"]
      valid_through:
        type: string
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `data_extraction_goal` | string | — | **Required.** What data to extract. |
| `url` | string | — | URL to extract from. If omitted, uses current page. |
| `title` | string | `""` | Display title for this block. |
| `data_schema` | object/array/string | — | JSON Schema for the output structure. |
| `engine` | string | `"skyvern-1.0"` | AI engine to use (`"skyvern-1.0"` or `"skyvern-2.0"`). |
| `max_retries` | integer | `0` | Retry attempts. |
| `max_steps_per_run` | integer | — | Maximum steps allowed. |
| `parameter_keys` | array | — | Parameters this block can access. |
| `disable_cache` | boolean | `false` | Disable caching for this block. |

---

## Login

Authenticate to a website using stored credentials.

<CodeGroup>
```json JSON
{
  "block_type": "login",
  "label": "login_to_portal",
  "url": "{{website_url}}",
  "parameter_keys": ["credentials"],
  "navigation_goal": "Log in using the provided credentials. Handle any cookie consent or promotional popups first. COMPLETE when on the logged-in dashboard."
}
```

```yaml YAML
- block_type: login
  label: login_to_portal
  url: "{{website_url}}"
  parameter_keys:
    - credentials
  navigation_goal: |
    Log in using the provided credentials.
    Handle any cookie consent or promotional popups first.
    COMPLETE when on the logged-in dashboard.
    TERMINATE if login fails after 3 attempts.
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `url` | string | — | Login page URL. |
| `navigation_goal` | string | — | Additional instructions for complex login flows. |
| `title` | string | `""` | Display title for this block. |
| `engine` | string | `"skyvern-1.0"` | AI engine to use (`"skyvern-1.0"` or `"skyvern-2.0"`). |
| `parameter_keys` | array | — | Parameters including credential reference. |
| `error_code_mapping` | object | — | Map conditions to custom error codes. |
| `max_retries` | integer | `0` | Retry attempts. |
| `max_steps_per_run` | integer | — | Maximum steps allowed. |
| `complete_criterion` | string | — | Condition for completion. |
| `terminate_criterion` | string | — | Condition for termination. |
| `complete_verification` | boolean | `true` | Verify completion criteria. |
| `totp_identifier` | string | — | TOTP credential identifier for 2FA. |
| `totp_verification_url` | string | — | URL to fetch TOTP codes. |
| `disable_cache` | boolean | `false` | Disable caching for this block. |

---

## Task

Legacy block combining navigation and extraction. For new workflows, prefer separate Navigation and Extraction blocks.

<CodeGroup>
```json JSON
{
  "block_type": "task",
  "label": "login_and_extract",
  "url": "{{website_url}}",
  "parameter_keys": ["credentials"],
  "navigation_goal": "Log in using the provided credentials. Navigate to the account settings page. COMPLETE when on the settings page.",
  "data_extraction_goal": "Extract the account ID and subscription plan.",
  "data_schema": {
    "type": "object",
    "properties": {
      "account_id": { "type": "string" },
      "subscription_plan": { "type": "string" }
    }
  }
}
```

```yaml YAML
- block_type: task
  label: login_and_extract
  url: "{{website_url}}"
  parameter_keys:
    - credentials
  navigation_goal: |
    Log in using the provided credentials.
    Navigate to the account settings page.
    COMPLETE when on the settings page.
  data_extraction_goal: |
    Extract the account ID and subscription plan.
  data_schema:
    type: object
    properties:
      account_id:
        type: string
      subscription_plan:
        type: string
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `url` | string | — | Starting URL. |
| `navigation_goal` | string | — | What to do on the page. |
| `data_extraction_goal` | string | — | What data to extract. |
| `data_schema` | object/array/string | — | Schema for extracted data. |
| `title` | string | `""` | Display title for this block. |
| `engine` | string | `"skyvern-1.0"` | AI engine to use (`"skyvern-1.0"` or `"skyvern-2.0"`). |
| `parameter_keys` | array | — | Available parameters. |
| `error_code_mapping` | object | — | Custom error codes. |
| `max_steps_per_run` | integer | — | Maximum steps. |
| `max_retries` | integer | `0` | Retry attempts. |
| `complete_on_download` | boolean | `false` | Complete when download triggered. |
| `download_suffix` | string | — | Filename for the downloaded file. |
| `complete_criterion` | string | — | Condition for completion. |
| `terminate_criterion` | string | — | Condition for termination. |
| `complete_verification` | boolean | `true` | Verify completion criteria. |
| `include_action_history_in_verification` | boolean | `false` | Include action history in verification. |
| `totp_identifier` | string | — | TOTP credential identifier. |
| `totp_verification_url` | string | — | URL to fetch TOTP codes. |
| `disable_cache` | boolean | `false` | Disable caching. |

---

## Task V2

Simplified task block using natural language prompts. Uses computer-use agents for more flexible automation.

<CodeGroup>
```json JSON
{
  "block_type": "task_v2",
  "label": "complete_form",
  "url": "https://example.com/form",
  "prompt": "Fill out the contact form with the provided information and submit it. Wait for the confirmation message.",
  "max_iterations": 10,
  "max_steps": 25
}
```

```yaml YAML
- block_type: task_v2
  label: complete_form
  url: "https://example.com/form"
  prompt: |
    Fill out the contact form with the provided information and submit it.
    Wait for the confirmation message.
  max_iterations: 10
  max_steps: 25
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `prompt` | string | — | **Required.** Natural language description of the task. |
| `url` | string | — | Starting URL. |
| `max_iterations` | integer | `10` | Maximum number of iterations. |
| `max_steps` | integer | `25` | Maximum steps per iteration. |
| `totp_identifier` | string | — | TOTP credential identifier. |
| `totp_verification_url` | string | — | URL to fetch TOTP codes. |
| `disable_cache` | boolean | `false` | Disable caching. |

<Info>
`task_v2` does not use `parameter_keys`. All workflow parameters and previous block outputs are automatically available as Jinja2 template variables in `prompt` and `url`. For example: `"Fill the form with name {{first_name}} and email {{email}}"`.
</Info>

---

## Validation

Assert conditions using the LLM to control workflow flow.

<CodeGroup>
```json JSON
{
  "block_type": "validation",
  "label": "check_credential_status",
  "parameter_keys": ["extract_credentials_output"],
  "complete_criterion": "Continue if the certification_status is 'expired' or 'inactive', or if the valid_through date has changed.",
  "terminate_criterion": "Terminate if the certification_status is 'active' and valid_through matches current_credential_expiry."
}
```

```yaml YAML
- block_type: validation
  label: check_credential_status
  parameter_keys:
    - extract_credentials_output
  complete_criterion: |
    Continue if ANY of these are true:
    - certification_status is "expired"
    - certification_status is "inactive"
    - valid_through date has changed
  terminate_criterion: |
    Terminate (no email needed) if ALL of these are true:
    - certification_status is "active"
    - valid_through matches current_credential_expiry
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `complete_criterion` | string | — | Condition that must be true to continue. |
| `terminate_criterion` | string | — | Condition that terminates the workflow. |
| `parameter_keys` | array | — | Parameters to evaluate. |
| `error_code_mapping` | object | — | Map conditions to custom error codes. |
| `disable_cache` | boolean | `false` | Disable caching. |

---

## Conditional

Branch workflow execution based on conditions. Supports Jinja2 templates or LLM-based evaluation.

<CodeGroup>
```json JSON
{
  "block_type": "conditional",
  "label": "check_status",
  "branch_conditions": [
    {
      "criteria": {
        "criteria_type": "jinja2_template",
        "expression": "{{ status == 'approved' }}"
      },
      "next_block_label": "process_approved",
      "description": "Route to approval processing"
    },
    {
      "criteria": {
        "criteria_type": "jinja2_template",
        "expression": "{{ status == 'rejected' }}"
      },
      "next_block_label": "handle_rejection"
    },
    {
      "is_default": true,
      "next_block_label": "handle_pending"
    }
  ]
}
```

```yaml YAML
- block_type: conditional
  label: check_status
  branch_conditions:
    - criteria:
        criteria_type: jinja2_template
        expression: "{{ status == 'approved' }}"
      next_block_label: process_approved
      description: Route to approval processing
    - criteria:
        criteria_type: prompt
        expression: "Is the application status indicating rejection?"
      next_block_label: handle_rejection
    - is_default: true
      next_block_label: handle_pending
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `branch_conditions` | array | — | **Required.** List of conditions and their target blocks. |

**Branch Condition properties:**

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `criteria` | object | — | The condition to evaluate. |
| `criteria.criteria_type` | string | `"jinja2_template"` | `"jinja2_template"` or `"prompt"`. |
| `criteria.expression` | string | — | **Required.** Jinja2 expression or natural language prompt. |
| `criteria.description` | string | — | Description of the criteria. |
| `next_block_label` | string | — | Block to execute if condition is true. |
| `description` | string | — | Description of this branch. |
| `is_default` | boolean | `false` | If true, this branch is used when no other conditions match. |

---

## For Loop

Iterate over an array and execute nested blocks for each item.

<CodeGroup>
```json JSON
{
  "block_type": "for_loop",
  "label": "apply_to_jobs",
  "loop_over_parameter_key": "job_urls",
  "continue_on_failure": true,
  "loop_blocks": [
    {
      "block_type": "navigation",
      "label": "submit_application",
      "url": "{{submit_application.current_value}}",
      "navigation_goal": "Fill out and submit the job application."
    }
  ]
}
```

```yaml YAML
- block_type: for_loop
  label: apply_to_jobs
  loop_over_parameter_key: job_urls
  continue_on_failure: true
  loop_blocks:
    - block_type: navigation
      label: submit_application
      url: "{{submit_application.current_value}}"
      navigation_goal: |
        Fill out the job application form using:
        - Resume data: {{parsed_resume_output}}
        - Additional info: {{additional_information}}

        COMPLETE when application is submitted.
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `loop_blocks` | array | — | **Required.** Blocks to execute for each iteration. |
| `loop_over_parameter_key` | string | `""` | Parameter containing the array to iterate. |
| `loop_variable_reference` | string | — | Custom name for the loop variable. |
| `complete_if_empty` | boolean | `false` | If `true`, completes successfully when array is empty. |

<Info>
**Accessing the current item inside a loop**

Use `{{nested_block_label.current_value}}` to reference the current iteration value, where `nested_block_label` is the `label` of the block **inside** `loop_blocks` — not the label of the `for_loop` itself.

In the example above, the loop label is `apply_to_jobs` and the nested block label is `submit_application`, so the current URL is accessed as `{{submit_application.current_value}}`.
</Info>

The output of a `for_loop` block is an array containing the result from each iteration.

---

## Goto URL

Navigate directly to a URL without any AI processing.

<CodeGroup>
```json JSON
{
  "block_type": "goto_url",
  "label": "go_to_dashboard",
  "url": "https://app.example.com/dashboard"
}
```

```yaml YAML
- block_type: goto_url
  label: go_to_dashboard
  url: "https://app.example.com/dashboard"
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `url` | string | — | **Required.** URL to navigate to. |

---

## File Download

Navigate to download a file from a website.

<CodeGroup>
```json JSON
{
  "block_type": "file_download",
  "label": "download_ein_letter",
  "url": "https://irs.gov/ein/confirm",
  "navigation_goal": "Find and download the EIN confirmation letter PDF. Look for a \"Download\" or \"Print\" button. COMPLETE when download is triggered.",
  "download_suffix": "ein_confirmation.pdf"
}
```

```yaml YAML
- block_type: file_download
  label: download_ein_letter
  url: "https://irs.gov/ein/confirm"
  navigation_goal: |
    Find and download the EIN confirmation letter PDF.
    Look for a "Download" or "Print" button.
    COMPLETE when download is triggered.
  download_suffix: ein_confirmation.pdf
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `navigation_goal` | string | — | **Required.** How to find and download the file. |
| `url` | string | — | Starting URL. |
| `title` | string | `""` | Display title for this block. |
| `engine` | string | `"skyvern-1.0"` | AI engine to use (`"skyvern-1.0"` or `"skyvern-2.0"`). |
| `download_suffix` | string | — | Filename for the downloaded file. |
| `download_timeout` | number | — | Timeout in seconds for download. |
| `parameter_keys` | array | — | Parameters this block can access. |
| `error_code_mapping` | object | — | Map conditions to custom error codes. |
| `max_retries` | integer | `0` | Retry attempts. |
| `max_steps_per_run` | integer | — | Maximum steps. |
| `totp_identifier` | string | — | TOTP credential identifier. |
| `totp_verification_url` | string | — | URL to fetch TOTP codes. |
| `disable_cache` | boolean | `false` | Disable caching. |

Downloaded files are stored in `SKYVERN_DOWNLOAD_DIRECTORY`—use this path in `upload_to_s3`, `file_upload`, or `send_email`'s `file_attachments` to access them.

---

## File Parser

Download and parse a file from a URL. Supports CSV, Excel, and PDF files.

<CodeGroup>
```json JSON
{
  "block_type": "file_url_parser",
  "label": "parse_order_csv",
  "file_url": "{{order_file_url}}",
  "file_type": "csv"
}
```

```yaml YAML
- block_type: file_url_parser
  label: parse_order_csv
  file_url: "{{order_file_url}}"
  file_type: csv
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `file_url` | string | — | **Required.** URL of the file to parse. |
| `file_type` | string | — | **Required.** One of: `csv`, `excel`, `pdf`. |
| `json_schema` | object | — | Schema for structured extraction. |

---

## PDF Parser

<Warning>
Deprecated. Use [File Parser](#file-parser) with `file_type: "pdf"` instead. This block will be removed in a future version.
</Warning>

Parse a PDF file specifically for text extraction.

<CodeGroup>
```json JSON
{
  "block_type": "pdf_parser",
  "label": "parse_resume",
  "file_url": "{{resume}}"
}
```

```yaml YAML
- block_type: pdf_parser
  label: parse_resume
  file_url: "{{resume}}"
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `file_url` | string | — | **Required.** URL of the PDF file. |
| `json_schema` | object | — | Schema for structured extraction from PDF. |

---

## Download to S3

Download a file from a URL directly to S3 storage.

<CodeGroup>
```json JSON
{
  "block_type": "download_to_s3",
  "label": "save_report",
  "url": "https://example.com/report.pdf"
}
```

```yaml YAML
- block_type: download_to_s3
  label: save_report
  url: "https://example.com/report.pdf"
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `url` | string | — | **Required.** URL of the file to download. |

---

## Upload to S3

Upload files from the workflow to S3 storage.

<CodeGroup>
```json JSON
{
  "block_type": "upload_to_s3",
  "label": "upload_results",
  "path": "{{download_report_output}}"
}
```

```yaml YAML
- block_type: upload_to_s3
  label: upload_results
  path: "{{download_report_output}}"
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `path` | string | — | Path to the file to upload. |

---

## File Upload

Upload downloaded files to AWS S3 or Azure Blob storage.

<CodeGroup>
```json JSON
{
  "block_type": "file_upload",
  "label": "upload_to_s3",
  "storage_type": "s3",
  "aws_access_key_id": "{{aws_access_key}}",
  "aws_secret_access_key": "{{aws_secret_key}}",
  "s3_bucket": "company-invoices",
  "region_name": "us-west-2",
  "path": "SKYVERN_DOWNLOAD_DIRECTORY"
}
```

```yaml YAML
- block_type: file_upload
  label: upload_to_s3
  storage_type: s3
  aws_access_key_id: "{{aws_access_key}}"
  aws_secret_access_key: "{{aws_secret_key}}"
  s3_bucket: "company-invoices"
  region_name: us-west-2
  path: SKYVERN_DOWNLOAD_DIRECTORY
```
</CodeGroup>

**S3 Parameters:**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `storage_type` | string | — | Set to `"s3"` for AWS S3. |
| `aws_access_key_id` | string | — | AWS access key. |
| `aws_secret_access_key` | string | — | AWS secret key. |
| `s3_bucket` | string | — | Target S3 bucket name. |
| `region_name` | string | — | AWS region. |
| `path` | string | — | Path to the file to upload. |

**Azure Parameters:**

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `storage_type` | string | — | Set to `"azure"` for Azure Blob Storage. |
| `azure_storage_account_name` | string | — | Azure storage account name. |
| `azure_storage_account_key` | string | — | Azure storage account key. |
| `azure_blob_container_name` | string | — | Azure blob container name. |
| `azure_folder_path` | string | — | Folder path within the container. |
| `path` | string | — | Path to the file to upload. |

---

## HTTP Request

Make HTTP API calls to external services.

<CodeGroup>
```json JSON
{
  "block_type": "http_request",
  "label": "post_to_webhook",
  "method": "POST",
  "url": "https://api.example.com/webhook",
  "headers": {
    "Authorization": "Bearer {{api_token}}",
    "Content-Type": "application/json"
  },
  "body": {
    "data": "{{extracted_data}}"
  },
  "timeout": 30
}
```

```yaml YAML
- block_type: http_request
  label: post_to_webhook
  method: POST
  url: "https://api.example.com/webhook"
  headers:
    Authorization: "Bearer {{api_token}}"
    Content-Type: application/json
  body:
    data: "{{extracted_data}}"
  timeout: 30
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `url` | string | — | URL to make the request to. |
| `method` | string | `"GET"` | HTTP method: GET, POST, PUT, DELETE, etc. |
| `headers` | object | — | HTTP headers as key-value pairs. |
| `body` | object | — | Request body (for POST, PUT, etc.). |
| `files` | object | — | Files to upload as multipart form data. |
| `timeout` | integer | `30` | Request timeout in seconds. |
| `follow_redirects` | boolean | `true` | Whether to follow HTTP redirects. |
| `download_filename` | string | — | Filename for downloaded response. |
| `save_response_as_file` | boolean | `false` | Save response body as a file. |
| `parameter_keys` | array | — | Parameters this block can access. |

---

## Send Email

Send an email with optional attachments.

<CodeGroup>
```json JSON
{
  "block_type": "send_email",
  "label": "send_confirmation",
  "smtp_host_secret_parameter_key": "smtp_host",
  "smtp_port_secret_parameter_key": "smtp_port",
  "smtp_username_secret_parameter_key": "smtp_username",
  "smtp_password_secret_parameter_key": "smtp_password",
  "sender": "notifications@company.com",
  "recipients": ["{{recipient_email}}", "compliance@company.com"],
  "subject": "EIN Registration Complete - {{company_name}}",
  "body": "Your EIN registration has been completed. See attached for details.",
  "file_attachments": ["SKYVERN_DOWNLOAD_DIRECTORY"]
}
```

```yaml YAML
- block_type: send_email
  label: send_confirmation
  smtp_host_secret_parameter_key: smtp_host
  smtp_port_secret_parameter_key: smtp_port
  smtp_username_secret_parameter_key: smtp_username
  smtp_password_secret_parameter_key: smtp_password
  sender: notifications@company.com
  recipients:
    - "{{recipient_email}}"
    - compliance@company.com
  subject: "EIN Registration Complete - {{company_name}}"
  body: |
    Your EIN registration has been completed.
    EIN: {{extract_ein_output.ein_number}}
  file_attachments:
    - SKYVERN_DOWNLOAD_DIRECTORY
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `smtp_host_secret_parameter_key` | string | — | **Required.** Parameter key for SMTP host. |
| `smtp_port_secret_parameter_key` | string | — | **Required.** Parameter key for SMTP port. |
| `smtp_username_secret_parameter_key` | string | — | **Required.** Parameter key for SMTP username. |
| `smtp_password_secret_parameter_key` | string | — | **Required.** Parameter key for SMTP password. |
| `sender` | string | — | **Required.** Sender email address. |
| `recipients` | array | — | **Required.** List of recipient email addresses. |
| `subject` | string | — | **Required.** Email subject line. |
| `body` | string | — | **Required.** Email body content. |
| `file_attachments` | array | — | Files to attach. Use `SKYVERN_DOWNLOAD_DIRECTORY` for downloaded files. |

---

## Code

Execute custom Python code for data transformation or browser control.

<CodeGroup>
```json JSON
{
  "block_type": "code",
  "label": "calculate_price_diff",
  "parameter_keys": ["alibaba_price", "amazon_price"],
  "code": "if amazon_price and alibaba_price:\n    result = {'difference': alibaba_price - amazon_price}\nelse:\n    result = None"
}
```

```yaml YAML
- block_type: code
  label: calculate_price_diff
  parameter_keys:
    - alibaba_price
    - amazon_price
  code: |
    if amazon_price and alibaba_price:
        result = {
            "difference": alibaba_price - amazon_price,
            "percentage": ((alibaba_price - amazon_price) / amazon_price) * 100
        }
    else:
        result = None
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `code` | string | — | **Required.** Python code to execute. Store result in `result` variable. |
| `parameter_keys` | array | — | Parameters available to the code. |

Available objects: `skyvern_page` (Playwright page object for browser control).

<Note>
Code Block with browser control is invite-only on Skyvern Cloud. Contact support@skyvern.com for access.
</Note>

---

## Text Prompt

Make an LLM call for text generation or analysis.

<CodeGroup>
```json JSON
{
  "block_type": "text_prompt",
  "label": "summarize_credentials",
  "llm_key": "OPENAI_GPT4O",
  "parameter_keys": ["extract_credentials_output"],
  "prompt": "Analyze these professional credentials and provide a summary including current status, any concerns, and recommended actions: {{extract_credentials_output}}",
  "json_schema": {
    "type": "object",
    "properties": {
      "status_summary": { "type": "string" },
      "concerns": { "type": "array", "items": { "type": "string" } }
    }
  }
}
```

```yaml YAML
- block_type: text_prompt
  label: summarize_credentials
  llm_key: OPENAI_GPT4O
  parameter_keys:
    - extract_credentials_output
  prompt: |
    Analyze these professional credentials and provide a summary:
    {{extract_credentials_output}}

    Include: Current status, any concerns, recommended actions
  json_schema:
    type: object
    properties:
      status_summary:
        type: string
      concerns:
        type: array
        items:
          type: string
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `prompt` | string | — | **Required.** The prompt to send to the LLM. |
| `parameter_keys` | array | — | Parameters available in the prompt. |
| `llm_key` | string | — | Model to use (e.g., `OPENAI_GPT4O`). |
| `json_schema` | object | — | Schema for structured output. |

---

## Print Page

Save the current browser page as a PDF file.

<CodeGroup>
```json JSON
{
  "block_type": "print_page",
  "label": "save_receipt",
  "custom_filename": "receipt_{{order_id}}",
  "format": "Letter",
  "landscape": false,
  "print_background": true
}
```

```yaml YAML
- block_type: print_page
  label: save_receipt
  custom_filename: "receipt_{{order_id}}"
  format: Letter
  landscape: false
  print_background: true
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `custom_filename` | string | — | Custom filename for the PDF. |
| `format` | string | `"A4"` | Page format: `A4`, `Letter`, `Legal`, or `Tabloid`. |
| `landscape` | boolean | `false` | Print in landscape orientation. |
| `print_background` | boolean | `true` | Include background colors and images. |
| `include_timestamp` | boolean | `true` | Include timestamp in filename. |
| `parameter_keys` | array | — | Parameters this block can access. |

<Note>
The `print_page` block works via the REST API and TypeScript SDK, but the Python SDK's generated types do not yet include it. If you use the Python SDK, pass the block definition through `json_definition` or `yaml_definition` — the API will accept it.
</Note>

---

## Wait

Pause workflow execution for a specified duration.

<CodeGroup>
```json JSON
{
  "block_type": "wait",
  "label": "wait_for_processing",
  "wait_sec": 30
}
```

```yaml YAML
- block_type: wait
  label: wait_for_processing
  wait_sec: 30
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `wait_sec` | integer | `0` | Seconds to wait. |

---

## Human Interaction

Pause the workflow and send an email requesting human approval before continuing.

<CodeGroup>
```json JSON
{
  "block_type": "human_interaction",
  "label": "request_approval",
  "instructions": "Please review the extracted data and approve or reject to continue.",
  "positive_descriptor": "Approve",
  "negative_descriptor": "Reject",
  "timeout_seconds": 7200,
  "sender": "workflow@company.com",
  "recipients": ["manager@company.com"],
  "subject": "Approval Required - Order Processing",
  "body": "An order requires your approval before processing can continue."
}
```

```yaml YAML
- block_type: human_interaction
  label: request_approval
  instructions: Please review the extracted data and approve or reject to continue.
  positive_descriptor: Approve
  negative_descriptor: Reject
  timeout_seconds: 7200
  sender: workflow@company.com
  recipients:
    - manager@company.com
  subject: "Approval Required - Order Processing"
  body: |
    An order requires your approval before processing can continue.

    Order details: {{order_details}}
```
</CodeGroup>

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `timeout_seconds` | integer | — | **Required.** How long to wait for a response (in seconds). |
| `sender` | string | — | **Required.** Email address to send from. |
| `recipients` | array | — | **Required.** List of email addresses to notify. |
| `subject` | string | — | **Required.** Email subject line. |
| `body` | string | — | **Required.** Email body content. |
| `instructions` | string | `"Please review and approve or reject to continue the workflow."` | Instructions shown in the approval interface. |
| `positive_descriptor` | string | `"Approve"` | Label for the approval button. |
| `negative_descriptor` | string | `"Reject"` | Label for the rejection button. |

---

## Next steps

<CardGroup cols={2}>
  <Card
    title="Build a Workflow"
    icon="hammer"
    href="/multi-step-automations/build-a-workflow"
  >
    Create and run your first workflow
  </Card>
  <Card
    title="Workflow Parameters"
    icon="sliders"
    href="/multi-step-automations/workflow-parameters"
  >
    Pass data between blocks with parameters
  </Card>
  <Card
    title="File Operations"
    icon="file"
    href="/multi-step-automations/file-operations"
  >
    Parse, download, and upload files
  </Card>
  <Card
    title="Webhooks"
    icon="bell"
    href="/going-to-production/webhooks"
  >
    Get notified when workflows complete
  </Card>
</CardGroup>
