Send Your First Task in 5 Minutes

This guide walks you through creating your first HumanRail task — from getting an API key to receiving a verified human judgment. Works with Python, TypeScript, and Go.

1

Get your API key

Sign up at humanrail.dev or log in to the customer dashboard. Navigate to Settings → API Keys and generate a new key.

Note

API keys are prefixed with ek_live_ for production and ek_test_ for sandbox. Use the sandbox key during development — it simulates worker responses without hitting the real worker pool.

Set the key as an environment variable:

bash
export HUMANRAIL_API_KEY="ek_test_your_key_here"
2

Install the SDK

Choose your language and install the HumanRail client library.

bash
pip install humanrail
bash
npm install @humanrail/sdk
bash
go get github.com/prime001/humanrail-sdk/go
3

Send your first task

A task is a unit of work routed to a vetted human worker. You define the input payload, the expected output schema, and a payout amount. HumanRail handles routing, verification, and payment.

Python
from humanrail import HumanRail

client = HumanRail(api_key="ek_live_...")

task = client.tasks.create(
    type="content_review",
    payload={
        "text": "Is this review genuine?",
        "content": "Great product, 5 stars!",
    },
    output_schema={
        "type": "object",
        "required": ["verdict"],
        "properties": {
            "verdict": {
                "type": "string",
                "enum": ["genuine", "ai_generated", "uncertain"],
            },
            "notes": {"type": "string"},
        },
    },
    payout_sats=500,
    sla_seconds=300,
    skills_required=["content_review"],
)

print(f"Task created: {task.id}")
# Task created: 01abc123-...
TypeScript
import { HumanRail } from '@humanrail/sdk';

const client = new HumanRail({ apiKey: 'ek_live_...' });

const task = await client.tasks.create({
  type: 'content_review',
  payload: {
    text: 'Is this review genuine?',
    content: 'Great product, 5 stars!',
  },
  outputSchema: {
    type: 'object',
    required: ['verdict'],
    properties: {
      verdict: {
        type: 'string',
        enum: ['genuine', 'ai_generated', 'uncertain'],
      },
      notes: { type: 'string' },
    },
  },
  payoutSats: 500,
  slaSeconds: 300,
  skillsRequired: ['content_review'],
});

console.log(`Task created: ${task.id}`);
// Task created: 01abc123-...
Go
package main

import (
    "context"
    "fmt"

    humanrail "github.com/prime001/humanrail-sdk/go"
)

func main() {
    client := humanrail.NewClient("ek_live_...")

    task, err := client.Tasks.Create(context.Background(), &humanrail.CreateTaskRequest{
        Type: "content_review",
        Payload: map[string]any{
            "text":    "Is this review genuine?",
            "content": "Great product, 5 stars!",
        },
        PayoutSats:     500,
        SLASeconds:     300,
        SkillsRequired: []string{"content_review"},
    })
    if err != nil {
        panic(err)
    }

    fmt.Println("Task created:", task.ID)
}
What happens next?

When you call tasks.create(), HumanRail assigns the task to a qualified worker within seconds. The worker completes the task, their response passes through our 6-stage verification pipeline, and you receive the verified result.

4

Get the result

There are two ways to receive the verified result: webhooks (recommended for production) or polling (simpler for development).

Option A: Webhooks (recommended)

Register a webhook endpoint to receive real-time notifications. HumanRail will POST a task.verified event when the worker's response passes verification. See the Webhooks guide for full details.

Python (FastAPI)
from fastapi import FastAPI, Request, HTTPException
from humanrail import verify_webhook_signature
import os

app = FastAPI()

@app.post("/webhooks/humanrail")
async def handle_webhook(request: Request):
    body = await request.body()
    signature = request.headers.get("x-humanrail-signature")

    if not verify_webhook_signature(
        payload=body,
        signature=signature,
        secret=os.environ["HUMANRAIL_WEBHOOK_SECRET"],
    ):
        raise HTTPException(status_code=401)

    event = await request.json()
    if event["type"] == "task.verified":
        print("Result:", event["data"]["output"])
        # {"verdict": "genuine", "notes": "Appears authentic"}

    return {"ok": True}
TypeScript (Express)
import express from 'express';
import { verifyWebhookSignature } from '@humanrail/sdk';

const app = express();

app.post('/webhooks/humanrail',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const signature = req.headers['x-humanrail-signature'];
    const isValid = verifyWebhookSignature({
      payload: req.body,
      signature,
      secret: process.env.HUMANRAIL_WEBHOOK_SECRET,
    });

    if (!isValid) return res.status(401).send('Invalid signature');

    const event = JSON.parse(req.body);
    if (event.type === 'task.verified') {
      console.log('Result:', event.data.output);
      // { verdict: "genuine", notes: "Appears authentic" }
    }

    res.sendStatus(200);
  }
);
Go
func webhookHandler(w http.ResponseWriter, r *http.Request) {
    body, _ := io.ReadAll(r.Body)
    signature := r.Header.Get("X-Humanrail-Signature")

    if !humanrail.VerifyWebhookSignature(body, signature, webhookSecret) {
        http.Error(w, "Invalid signature", http.StatusUnauthorized)
        return
    }

    var event humanrail.WebhookEvent
    json.Unmarshal(body, &event)

    if event.Type == "task.verified" {
        fmt.Println("Result:", event.Data.Output)
    }

    w.WriteHeader(http.StatusOK)
}

Option B: Polling

For development or simple scripts, you can poll the task status until it reaches a terminal state.

Python
import time

while True:
    task = client.tasks.get(task.id)

    if task.status == "verified":
        print("Result:", task.output)
        break
    elif task.status in ("failed", "expired", "cancelled"):
        print(f"Task ended: {task.status}")
        break

    time.sleep(5)  # poll every 5 seconds
TypeScript
const waitForResult = async (taskId: string) => {
  while (true) {
    const task = await client.tasks.get(taskId);

    if (task.status === 'verified') return task.output;
    if (['failed', 'expired', 'cancelled'].includes(task.status)) {
      throw new Error(`Task ended: ${task.status}`);
    }

    await new Promise(r => setTimeout(r, 5000));
  }
};

const output = await waitForResult(task.id);
console.log(output);
// { verdict: "genuine", notes: "Appears authentic" }
Go
// Use the built-in helper that polls for you
result, err := client.Tasks.WaitForCompletion(
    context.Background(), task.ID, nil,
)
if err != nil {
    panic(err)
}
fmt.Println("Result:", result.Output)
Tip

Webhooks are strongly recommended for production. Polling works for development and simple scripts, but adds latency and wastes resources. Use the task.verified webhook event for real-time results.

5

Common task types

HumanRail supports any task type you define. Here are some common ones to get you started:

Task Type Description Typical SLA Typical Payout
content_review Determine if user-generated content is genuine, AI-generated, or policy-violating 5 min 200-500 sats
refund_eligibility Evaluate whether a refund request meets your return policy criteria 5 min 300-800 sats
document_verification Verify that an uploaded document (ID, proof of address) is valid and matches claims 15 min 500-2000 sats
sentiment_analysis Classify the sentiment and intent of customer messages when AI confidence is low 3 min 100-300 sats
image_moderation Classify images as safe, NSFW, violent, or policy-violating 5 min 200-500 sats
translation_review Verify machine translation accuracy and cultural appropriateness 10 min 500-1500 sats
Custom task types

You can create any task type with any output schema. Define the outputSchema as a JSON Schema object and HumanRail will auto-generate the worker form and validate submissions against it.

Next steps

🔌

Webhook Setup

Event types, signature verification, retry policy, and best practices.

📖

API Reference

Full endpoint documentation with request and response schemas.

📦

SDKs

TypeScript, Python, and Go client libraries with full guides.