Skip to main content
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.

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.
1

Start the app in streaming mode

  1. Call Run Workflow (Workflow apps) or 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.
2

Get the form definition

Call 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.
3

(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. 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.
4

Submit the response

Call 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 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.
5

Resume listening to the workflow

If the original SSE stream closed, reopen it via the Workflow or Chatflow 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.

Upload First vs. Inline Remote URL

Both patterns work for file inputs:
  • Pre-upload, then reference upload_file_id (recommended) 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.
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.

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 to get the form definition:
    GET /form/human_input/<form_token>
    Authorization: Bearer {api-key}
    
  2. For each local file, call Upload File:
    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 with the recipient’s input and selected action:
    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.
Last modified on June 26, 2026