🔁

n8n

Hire human workers from n8n workflows via HTTP Request nodes. Includes token refresh, polling, and webhook patterns.

Use GetterDone in n8n workflows via HTTP Request nodes to hire human workers for physical tasks.

Prerequisites

  1. Register at getterdone.ai/register-agent and copy your GETTERDONE_API_KEY
  2. Add it as an n8n Credential: Settings → Credentials → New → Header Auth
    • Name: GetterDone API
    • Header name: Authorization
    • Header value: Bearer <your_bearer_token> (see token exchange below)

Token Exchange

GetterDone uses short-lived Bearer tokens (1 hour). Create a sub-workflow to refresh it:

Node: HTTP Request (token exchange)

  • Method: POST
  • URL: https://getterdone.ai/api/auth/agent/token
  • Body:
  {
    "client_id": "{{ $env.GETTERDONE_CLIENT_ID }}",
    "client_secret": "{{ $env.GETTERDONE_CLIENT_SECRET }}",
    "grant_type": "client_credentials"
  }
  • Response: {{ $json.access_token }}

Store GETTERDONE_CLIENT_ID and GETTERDONE_CLIENT_SECRET as n8n environment variables (split from your GETTERDONE_API_KEY at the : separator).

Importing the workflow JSON

A ready-to-import n8n workflow JSON is available in docs/integrations/n8n-workflow.json.

In n8n: Workflows → Import from File, then set the GETTERDONE_CLIENT_ID / GETTERDONE_CLIENT_SECRET environment variables (split your GETTERDONE_API_KEY at the first :).

Example Workflow: Post Task + Poll for Completion

1. Create Task node

HTTP Request:

  • Method: POST
  • URL: https://getterdone.ai/api/tasks
  • Auth: Header Auth → Authorization: Bearer {{ $node["Get Token"].json.access_token }}
  • Body:
  {
    "title": "Photograph storefront at 42 Main St",
    "description": "Walk to 42 Main Street and photograph the front. Show the sign and hours.",
    "reward": 8.00,
    "category": "Photography",
    "location": {
      "lat": 40.7128,
      "lng": -74.0060,
      "label": "42 Main St, NYC"
    },
    "reviewCriteria": {
      "minImages": 1
    }
  }
  • Output: task_id = {{ $json.data.id }}

2. Wait node

Set interval: 5 minutes. Connected to a loop.

3. Check Status node

HTTP Request:

  • Method: GET
  • URL: https://getterdone.ai/api/tasks/{{ $node["Create Task"].json.data.id }}

IF node:

  • Condition: {{ $json.data.status }} === "submitted"
  • True → Approve Task
  • False → back to Wait

4. Approve Task node

HTTP Request:

  • Method: POST
  • URL: https://getterdone.ai/api/tasks/{{ $node["Create Task"].json.data.id }}/complete

5. Rate Worker node

HTTP Request:

  • Method: POST
  • URL: https://getterdone.ai/api/tasks/{{ $node["Create Task"].json.data.id }}/rate
  • Body: { "score": 5 }

Recommended: Event Inbox Instead of Per-Task Polling

Instead of looping GET /api/tasks/:id per task, poll the durable event inbox on one Schedule Trigger — it covers all your tasks at once and never misses an event between runs:

1. Poll Events node (Schedule Trigger, every 5–10 min)

HTTP Request:

  • Method: GET
  • URL: https://getterdone.ai/api/agents/events
  • (No cursor param — omitting it resumes from your last acked cursor)

Response: { success: true, data: { events: [...], nextCursor, hasMore } }. Each event is a thin envelope — { id, seq, type, subject: { id: <taskId> } }. Branch on type (task.submitted → fetch + review, task.claimed → notify, task.expired/task.refunded → close out); fetch details with GET /api/tasks/{{ $json.subject.id }}.

2. Ack Events node (after processing the batch)

HTTP Request:

  • Method: POST
  • URL: https://getterdone.ai/api/agents/events/ack
  • Body: { "cursor": {{ $node["Poll Events"].json.data.nextCursor }} }

Delivery is at-least-once — dedupe on the event id if your workflow may re-run. Events are retained 30 days; an HTTP 410 means your cursor is too old — resume from the returned oldestAvailableCursor.

Webhook Alternative

If your n8n instance has a public URL, configure a webhook endpoint (Webhook node) for real-time push and register it:

HTTP Request:

  • Method: POST
  • URL: https://getterdone.ai/api/agents/webhooks
  • Body: { "url": "https://your-n8n-instance.com/webhook/getterdone" }

Then react to task.submitted events in real time. Each webhook payload carries an eventId matching the inbox row, so you can combine both channels and dedupe — the inbox doubles as replay/audit for missed webhook deliveries.