Skip to main content

n8n

Connect n8n to FinalSay using the community package n8n-nodes-finalsay (in-repo: finalsay-n8n-nodes/), or using the HTTP Request node with the Agent API.

Community nodes (n8n-nodes-finalsay)

The package adds:
  • FinalSay: Create approvalPOST /v1/approvals. In the node form, Request ID / Correlation toggles sit after the optional Override timeout block; Send callback is the last section (defaults: execution id for request_id and correlation_id; default callback {{ $execution.resumeUrl }} when a callback is wanted). Optional timeout override and Callback headers (non-secret metadata only; see Securing the Wait resume URL).
  • FinalSay: Wait for approval — Same create fields; posts POST /v1/approvals with callback.url set to the execution resume URL, then pauses until FinalSay posts the result. One n8n input item per run. Resume webhook authentication matches n8n’s Wait node (None / Header / Basic / JWT). Output merges the create response with final_result. The node is usableAsTool, so n8n also registers Tool / HitlTool variants for the AI Agent (see below).
  • FinalSay: Fetch result (GET)GET /v1/approvals/:requestId/result (e.g. if you poll instead of a callback, or to re-read after create).
Install from the monorepo (npm run build in finalsay-n8n-nodes, then npm link or copy into n8n’s custom nodes path), or from npm when published. See finalsay-n8n-nodes/README.md.

AI Agent tools and HitlTool

n8n auto-derives two extra node types from FinalSay: Wait for approval (same mechanism as built-in send-and-wait integrations such as Gmail; labels in the editor start from that node’s display name): Self-hosted: set environment variable N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true (n8n ≥ 1.79) so community packages are allowed as AI tools. Restart n8n after installing or upgrading the package. Shape reference: finalsay-n8n-nodes/examples/ai-agent-finalsay-tool.example.json. To create approvals only via MCP and handle Wait / resume URLs yourself in the workflow, use the FinalSay MCP adapter tools create_approval or request_human_approval with optional callback — see MCP. You can still use HTTP Request for full control or unusual payloads.

Human gate before another MCP server

To run a human approval step in n8n before calling a different MCP server (not the FinalSay adapter), wire FinalSay: Wait for approval → (optional IF / Switch on final_result) → n8n’s built-in MCP Client Tool. The community package supplies the approval/wait nodes; it does not embed the MCP client—that stays a separate node on the canvas. Reference: finalsay-n8n-nodes/examples/human-gate-before-mcp.example.json and Human review before a different MCP tool in finalsay-n8n-nodes/README.md.

Prerequisites

  • Workspace API key from the web dashboard (or the same place you manage integrations). The community nodes use the production Agent API at https://api.finalsay-hitl.com; you pick the agent in each node from a dropdown.
  • Familiarity with n8n HTTP Request nodes and, for callbacks, Webhook nodes.

Headers for every request

Add these to your HTTP Request node (or expression equivalent):

Create an approval

  1. Add an HTTP Request node.
  2. Method POST, URL: {BASE_URL}/v1/approvals
  3. Body: JSON matching Agent API: POST /v1/approvals (question, context_markdown, options, and optionally timeout, callback, or request_id). Omit timeout to use the agent’s dashboard defaults.
Save the response field request_id for polling (the API returns one whether you sent your own or the server generated it).

Get the result

  1. In the create payload, set callback.url to a URL n8n exposes (e.g. Webhook node in “Test” or production URL).
  2. Run your workflow; when a human resolves the approval, the service POSTs the final payload to your webhook.
  3. Parse the JSON in a following node.

Option B — Polling

  1. After creation, poll GET {BASE_URL}/v1/approvals/{requestId}/result where {requestId} is the request_id from the create response (or the same value if you set request_id in the body yourself).
  2. If the body is { "status": "pending" }, wait and repeat (use Wait node or a loop with delay).
  3. When resolved, the response includes the full result object—see Agent API.

Securing the Wait resume URL

When you use WaitOn Webhook Call, n8n gives you {{ $execution.resumeUrl }}. Anyone who obtains that URL could resume the execution unless you protect the Wait node. Recommended (Wait-compatible): agent-level callback auth
  1. In the FinalSay web dashboard, open the agent → SettingsCallback webhook authentication.
  2. Choose a header name (default X-FinalSay-Callback) and click Generate secret (or Rotate secret). Copy the value once; it is not shown again.
  3. In n8n, on the Wait node, set Authentication to Header Auth (or equivalent) and enter the same header name and value as in the dashboard.
  4. In FinalSay: Create approval, set Callback URL to {{ $execution.resumeUrl }} as usual. You can leave Callback headers empty unless you need extra non-secret headers.
FinalSay merges the dashboard secret into the outbound callback on the server when the approval resolves. The secret does not belong in workflow JSON, callback.headers on create, or MCP tool arguments—so it is not leaked in exports. If the same header name appears in both Callback headers on the node and agent callback auth, the agent value wins.

Troubleshooting 403 on the resume URL

  • Header never sent — Outbound callback auth exists only after you Generate secret in the agent Settings tab. If callback auth is not configured, FinalSay does not add the header; n8n Header Auth on Wait / FinalSay: Wait for approval still expects it → 403.
  • Name or value mismatch — Use the same header name as in the dashboard (default X-FinalSay-Callback) and paste the generated secret into the n8n Header Auth credential’s value. After Rotate secret, update the credential; the previous secret is invalid.
  • IP allowlist — On FinalSay: Wait for approval, open Resume webhook: advancedIP(s) Allowlist; leave it empty, or list the addresses FinalSay uses; otherwise n8n returns 403 (IP is not allowed).
  • Ignore bots — With Ignore bots enabled, unusual User-Agent strings may be rejected.

Tips

  • You can omit request_id; the API assigns a UUID. Add your own stable request_id when you need idempotent retries or to tie the approval to a workflow run id.
  • Respect rate limits on create; if you receive 429, slow down.
  • Idempotency: repeating the same client-supplied request_id with the same payload is safe; conflicting payloads return 409.