TurfAITurfAI Developers

Quickstart

Trigger your first TurfAI workflow over HTTP, from webhook to result.

This walkthrough takes you from nothing to a workflow result in four HTTP calls: create a webhook, trigger it, poll with the returned token, and read the output. You'll need a TurfAI account, a JWT (see Authentication), and the ID of a workflow (an "activity") to trigger.

Base URLs: staging is https://apisandbox.turfai.in/api, local development is http://localhost:1338/api. All examples below use staging.

The flow

1. Create a webhook for your workflow

A webhook binds a public trigger URL to one workflow (activity). This call needs your JWT.

curl -X POST https://apisandbox.turfai.in/api/webhooks \
  -H "Authorization: Bearer $TURFAI_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "activity": 123,
    "name": "Quickstart Webhook"
  }'
{
  "success": true,
  "data": {
    "id": 1,
    "name": "Quickstart Webhook",
    "url": "https://apisandbox.turfai.in/api/webhooks/trigger/1",
    "secret_key": "a1b2c3d4...64_char_hex...",
    "active": true,
    "trigger_count": 0
  }
}

Save the url and secret_key. The secret is shown in full only on create and regenerate — store it like a password.

2. Trigger the workflow

The trigger endpoint is public — it authenticates with the X-Webhook-Secret header, not your JWT. Any JSON body becomes the workflow's inputs.

curl -X POST https://apisandbox.turfai.in/api/webhooks/trigger/1 \
  -H "X-Webhook-Secret: $WEBHOOK_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "candidate_name": "Jane Smith",
    "email": "jane@example.com",
    "resume_file_id": "1ABC123xyz"
  }'
{
  "success": true,
  "execution_id": 456,
  "message": "Workflow execution started",
  "polling_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

You get back an execution_id and a short-lived polling_token (a JWT, ~1 hour) scoped to polling this one execution.

To send files, use multipart/form-data instead of JSON. Each uploaded file is stored as a document and injected into the workflow as inputs.<field>_file_url and inputs.<field>_document_id. See the event-driven and chatbot guides.

3. Poll for the result

Use the polling_token as a Bearer token to check status. Poll every 2–5 seconds and stop on a terminal status (completed or failed).

curl https://apisandbox.turfai.in/api/workflow-executions/456 \
  -H "Authorization: Bearer $POLLING_TOKEN"
{
  "data": {
    "id": 456,
    "status": "completed",
    "inputs": { "candidate_name": "Jane Smith" },
    "results": {
      "classification": { "type": "resume", "confidence": 0.95 },
      "extraction": { "name": "Jane Smith", "skills": ["Python", "ML"] }
    },
    "started_at": "2025-11-24T10:00:00.000Z",
    "completed_at": "2025-11-24T10:00:45.000Z"
  }
}

Status values: queued (waiting), running (executing), completed (success), failed (check the error field). A long-running workflow with a human step can also report awaiting_user_input — see the HITL guide.

4. Read the output

The results object is keyed by what each node produced. Pull the field you need with JSONPath in your own code, or chain another task in the workflow that emails or POSTs the result somewhere.

A complete poller

import os, time, requests

BASE = "https://apisandbox.turfai.in/api"

def trigger(payload):
    r = requests.post(
        os.environ["WEBHOOK_URL"], json=payload,
        headers={"X-Webhook-Secret": os.environ["WEBHOOK_SECRET"]},
    )
    r.raise_for_status()
    return r.json()

def poll(execution_id, token, attempts=30):
    for _ in range(attempts):
        r = requests.get(f"{BASE}/workflow-executions/{execution_id}",
                         headers={"Authorization": f"Bearer {token}"})
        r.raise_for_status()
        data = r.json()["data"]
        if data["status"] == "completed":
            return data["results"]
        if data["status"] == "failed":
            raise RuntimeError(data.get("error"))
        time.sleep(2)
    raise TimeoutError("polling timed out")

started = trigger({"candidate_name": "Jane Smith", "resume_file_id": "1ABC123xyz"})
print(poll(started["execution_id"], started["polling_token"]))

Next steps

On this page