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

# Human Input API Integration Flow

> End-to-end sequence for handling a paused Human Input form via the API

When a workflow reaches a Human Input node, it pauses and emits a `human_input_required` event in the streaming response. The event carries a `form_token` that your integration uses to drive the form lifecycle until the workflow resumes.

For per-endpoint reference, see the [Human Input API](/api-reference/human-input/get-human-input-form).

## Sequence

The sequence below applies to both Workflow and Chatflow apps. Only the entry endpoint in Step 1 and the resume endpoint in Step 5 differ between the two.

<Steps>
  <Step title="Start the app in streaming mode">
    1. Call [Run Workflow](/api-reference/workflows/run-workflow) (Workflow apps) or [Send Chat Message](/api-reference/chatflows/send-chat-message) (Chatflow apps).
    2. Watch the SSE stream for the `human_input_required` event and capture its `form_token`.

       Every stream chunk also carries a `task_id`; keep it in case you need to resume listening in Step 5.
  </Step>

  <Step title="Get the form definition">
    Call [Get Human Input Form](/api-reference/human-input/get-human-input-form) with `form_token`. The response includes the rendered Markdown, input field definitions, available actions, pre-filled default values, and an `expiration_time` after which the form can no longer be submitted. Render the form for the recipient.
  </Step>

  <Step title="(File inputs only) Upload local files">
    If the recipient attaches a local file to a `file` or `file-list` input, upload it first with [Upload File](/api-reference/files/upload-file). It returns an `id` you reference as `upload_file_id` in the submit payload. Use one consistent `user` across the run, upload, and submit calls.

    A remote file needs no upload step: attach it inline in the submit as a `{transfer_method: remote_url, url}` mapping.
  </Step>

  <Step title="Submit the response">
    Call [Submit Human Input Form](/api-reference/human-input/submit-human-input-form) with the recipient's input values, the selected `action`, and your `user`. The `action` must be one of the actions from the form definition in Step 2.

    File inputs accept either a `{transfer_method: local_file, upload_file_id}` mapping (from Step 3) or an inline `{transfer_method: remote_url, url}` mapping. See [Upload First vs. Inline Remote URL](#upload-first-vs-inline-remote-url) for the trade-off.

    A successful submit is final: it closes the form and resumes the run along the matching action branch, so the same `form_token` can't be submitted again. A rejected submit (an invalid action, a missing required input, or a failed remote-file fetch) leaves the form unchanged — fix the inputs and resubmit with the same `form_token`.
  </Step>

  <Step title="Resume listening to the workflow">
    If the original SSE stream closed, reopen it via the [Workflow](/api-reference/workflows/stream-workflow-events) or [Chatflow](/api-reference/chatflows/stream-workflow-events) Stream Workflow Events API with the `task_id` from Step 1. The resumed run streams its remaining node events through to completion, like a run that never paused.
  </Step>
</Steps>

## Upload First vs. Inline Remote URL

Both patterns work for file inputs:

* **Pre-upload, then reference `upload_file_id`** (recommended)

  [Upload File](/api-reference/files/upload-file) validates file size, type, and extension at upload time, so the recipient gets immediate feedback and can retry before committing the whole submission.

* **Submit inline with `transfer_method: remote_url`**

  The backend fetches the file at submit time. Faster to integrate, but any size, type, or fetch failure rejects the entire submission, forcing the recipient to redo other fields.

<Tip>
  For interactive forms with recipient feedback, prefer the pre-upload pattern. The trade-off only pays off when the integration is fully programmatic and no human is waiting to retype anything.
</Tip>

## Delivery Method Requirement

The Human Input API works only with forms delivered via the Human Input node's WebApp method. Email-only delivery doesn't expose a `form_token`.

## Example: File-Attached Submission

This example uses a form with a `feedback` paragraph input, an `attachments` file-list input, and `approve` / `revise` actions.

1. Call [Get Human Input Form](/api-reference/human-input/get-human-input-form) to get the form definition:

   ```http theme={null}
   GET /form/human_input/<form_token>
   Authorization: Bearer {api-key}
   ```

2. For each local file, call [Upload File](/api-reference/files/upload-file):

   ```http theme={null}
   POST /files/upload
   Authorization: Bearer {api-key}
   Content-Type: multipart/form-data

   file=<binary>
   user=abc-123
   ```

   Returns `{"id": "1a77f0df-...", ...}`.

3. Call [Submit Human Input Form](/api-reference/human-input/submit-human-input-form) with the recipient's input and selected action:

   ```http theme={null}
   POST /form/human_input/<form_token>
   Authorization: Bearer {api-key}
   Content-Type: application/json

   {
     "inputs": {
       "feedback": "Looks good to ship",
       "attachments": [
         {"transfer_method": "local_file", "upload_file_id": "1a77f0df-..."}
       ]
     },
     "action": "approve",
     "user": "abc-123"
   }
   ```

   Returns `{}`. The workflow resumes along the `approve` branch.
