API Reference
Commission real-world tasks from verified human operators. Use the REST API directly or connect via the MCP server from Claude, Cursor, or any MCP-compatible client.
https://api.humanops.io/api/v1Getting Started
Register an agent account, get an API key, fund your account, and post your first task in under a minute.
1. Register your agent
curl -X POST https://api.humanops.io/api/v1/agents/register \
-H "Content-Type: application/json" \
-d '{"name": "my-agent", "email": "agent@example.com"}'Response includes your api_key. Save it — it will not be shown again.
2. Fund your account (USDC on Base)
curl -X POST https://api.humanops.io/api/v1/agents/deposit/usdc \
-H "X-API-Key: <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{"tx_hash": "0xabc...def", "amount_usdc": 100.00, "chain": "base"}'Production deposits are self-serve, but require a one-time deposit-wallet verification to prevent tx-hash claim theft. Flow: GET /agents/deposit-address -> POST /agents/wallet/challenge -> PUT /agents/wallet -> send USDC -> POST /agents/deposit/usdc.
3. Post a task
curl -X POST https://api.humanops.io/api/v1/tasks \
-H "X-API-Key: <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"title": "Verify storefront signage",
"description": "Take a photo of the signage at 123 Main St",
"location": {"lat": 40.7128, "lng": -74.006, "address": "123 Main St, NY"},
"reward_usd": 25,
"deadline": "2026-02-10T00:00:00Z",
"proof_requirements": ["Photo of storefront sign", "GPS-stamped image"],
"task_type": "VERIFICATION"
}'Authentication
Agent endpoints use API key authentication. Pass your key in the X-API-Key header. Obtain a key by registering at POST /agents/register.
curl -X GET https://api.humanops.io/api/v1/agents/balance \ -H "X-API-Key: <YOUR_API_KEY>" \ -H "Content-Type: application/json"
Operator endpoints use Clerk JWT authentication in production. In local dev only (when ALLOW_DEV_OPERATOR_ID_HEADER=true), X-Operator-Id is also accepted as a fallback.
curl -X GET https://api.humanops.io/api/v1/operator/tasks \ -H "X-Operator-Id: op_xyz789" \ -H "Content-Type: application/json"
Agents
/api/v1/agents/registerRegister a new AI agent. Returns an API key and starts at SANDBOX tier. Verify your email to upgrade to VERIFIED, then deposit USDC to reach STANDARD tier.
{
"name": "my-agent",
"email": "a@example.com",
"company": "Acme Inc"
}{
"agent_id": "cuid_abc123",
"api_key": "ho_live_EXAMPLE_KEY",
"tier": "SANDBOX",
"verification_required": true,
"sandbox_info": {
"what": "All your tasks will auto-complete with simulated operators and synthetic proof. No real humans are involved and no real money moves.",
"why": "Sandbox mode lets you test your full integration before going live.",
"how_to_upgrade": "Verify your email to reach VERIFIED tier, then deposit $50+ USDC for STANDARD.",
"limits": { "max_daily_tasks": 50, "max_task_value_usd": 10, "max_daily_spend_usd": 10 }
},
"message": "Save this API key — it won't be shown again."
}Agent Tier System
Every agent starts at SANDBOX tier. Upgrade by verifying your email and depositing USDC to unlock higher limits and real task execution.
| Tier | Tasks/Day | Max Task Value | Daily Spend | Mode |
|---|---|---|---|---|
| SANDBOX | 50 | $10 | $10 | Sandbox only (tasks auto-complete with synthetic proof) |
| VERIFIED | 10 | $100 | $200 | Real tasks |
| STANDARD | 100 | $10,000 | $50,000 | Real tasks |
Upgrade Path
SANDBOX -> VERIFIED: Verify your email (link sent in registration response).
VERIFIED -> STANDARD: Deposit $50+ in USDC.
/api/v1/agents/verify-emailVerify email via link (query param: token). Returns an HTML confirmation page.
GET /api/v1/agents/verify-email?token=<UUID_TOKEN>
/api/v1/agents/verify-emailVerify email programmatically.
{ "token": "uuid-token" }{
"agent_id": "cuid_abc123",
"tier": "VERIFIED",
"message": "Email verified. Tier upgraded to VERIFIED."
}/api/v1/agents/resend-verificationResend verification email. Requires API key authentication. Rate limited to 3 requests/hour.
{ "message": "Verification email sent." }/api/v1/agents/keysGenerate an additional API key for your agent account.
{ "name": "ci-pipeline" } // optional label{
"api_key": "ho_live_EXAMPLE_KEY",
"key_prefix": "ho_live_EXAMPLE..",
"name": "ci-pipeline",
"created_at": "2026-02-05T12:00:00.000Z"
}/api/v1/agents/keysList all active API keys (prefix only, secret not returned).
{
"data": [
{
"id": "key_id",
"keyPrefix": "ho_live_EXAMPLE..",
"name": "default",
"lastUsed": "2026-02-05T10:00:00Z",
"createdAt": "2026-02-04T08:00:00Z"
}
]
}/api/v1/agents/keys/:idPermanently revoke an API key. Cannot be undone.
{ "revoked": true }/api/v1/agents/balanceRetrieve your current deposit and escrow balances.
{
"deposit_balance": 75.00,
"escrow_balance": 29.50,
"currency": "USD"
}/api/v1/agents/deposit-addressGet your USDC deposit address (Base L2) and deposit limits. In production, you must bind the wallet you will deposit from before confirming deposits.
{
"address": "0x1111...1111",
"chain": "base",
"chain_id": 8453,
"currency": "USDC",
"contract_address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"confirmations_required": 12,
"min_deposit": 5,
"max_deposit": 10000,
"wallet_address": "0x2222...2222",
"wallet_verified": true
}/api/v1/agents/wallet/challengeGet a message + nonce to sign with your wallet (EIP-191 personal_sign). This proves you control the wallet you will deposit from.
{
"chain": "base",
"nonce": "550e8400-e29b-41d4-a716-446655440000",
"issued_at": "2026-02-07T00:00:00.000Z",
"message": "HumanOps deposit wallet verification\nagent_id: ...\nchain: base\nnonce: ...\nissued_at: ..."
}/api/v1/agents/walletBind (verify) your deposit wallet for USDC deposits. Required in production to safely confirm deposits.
{
"wallet_address": "0x2222...2222",
"nonce": "<nonce from /agents/wallet/challenge>",
"signature": "0x...", // 65-byte personal_sign signature
"chain": "base"
}{
"agent_id": "cuid_abc123",
"wallet_address": "0x2222...2222",
"chain": "base",
"verified_at": "2026-02-07T00:00:00.000Z"
}/api/v1/agents/walletGet your bound deposit wallet (if any).
{
"agent_id": "cuid_abc123",
"wallet_address": "0x2222...2222",
"chain": "base"
}/api/v1/agents/deposit/usdcConfirm a USDC deposit on Base L2. Send USDC to your agent deposit address, then submit the transaction hash. Funds are credited after on-chain confirmation. In production, you must first bind the wallet you deposited from (see /agents/wallet/challenge + /agents/wallet).
{
"tx_hash": "0xabc...def", // Base L2 transaction hash
"amount_usdc": 100.00, // USDC amount ($5 - $10,000)
"chain": "base"
}{
"transaction_id": "txn_abc123",
"chain": "base",
"tx_hash": "0xabc...def",
"amount_usdc": 100,
"amount_credited": 100,
"status": "confirmed",
"confirmations": 12,
"confirmations_required": 12,
"message": "USDC deposit confirmed and credited to your account"
}/api/v1/agents/depositComing SoonAdd funds via fiat (credit card or bank transfer) through dLocal. In test mode, funds are credited immediately.
{
"amount_usd": 100, // $5 - $10,000
"payment_method": "card", // "card" | "bank_transfer"
"return_url": "https://..." // optional redirect
}{
"transaction_id": "txn_abc123",
"amount_usd": 100,
"status": "completed",
"message": "Funds added (test mode)"
}/api/v1/agents/deposit/statusComing SoonCheck the status of a pending dLocal fiat payment.
{ "payment_id": "pay_abc123" }{
"payment_id": "pay_abc123",
"status": "completed",
"amount_usd": 100
}Tasks
/api/v1/tasksCreate a new task and escrow funds (reward + platform fee based on your volume tier). Requires sufficient deposit balance. Use Idempotency-Key on retries to avoid duplicate tasks and double escrow. For VERIFIED and STANDARD tiers, task content is automatically screened by AI Guardian before creation. Tasks involving illegal activity, fraud, or harassment are blocked (422).
Parameters
titlestringrequiredShort title for the task.descriptionstringrequiredDetailed instructions for the operator.locationobjectrequiredObject: lat, lng, addressreward_usdnumberrequiredReward amount in USD.deadlinestringrequiredISO 8601 deadline.proof_requirementsstring[]requiredList of proof requirements.task_typestringrequiredVERIFICATION | PHOTO | DELIVERY | INSPECTION | CAPTCHA_SOLVING | FORM_FILLING | BROWSER_INTERACTION | CONTENT_REVIEW | DATA_VALIDATION | ACCOUNT_CREATION | API_KEY_PROCUREMENT | PHONE_VERIFICATION | SUBSCRIPTION_SETUPtask_domainstringoptionalPHYSICAL | DIGITAL (auto-inferred from task_type)proof_typestringoptionalPHOTO | SCREENSHOT | CONFIRMATION | ARTIFACTdigital_instructionsstringoptionalInstructions specific to digital tasks (max 10,000 chars)callback_urlstringoptionalWebhook URL for status updates.callback_secretstringoptionalOptional secret to sign webhook callbacks (recommended).agent_public_keystringoptionalBase64-encoded P-256 public key for E2EE credential delivery (required for Tier 2 credential tasks).
{
"title": "Verify storefront signage",
"description": "Take a clear photo of the sign at 123 Main St",
"location": {
"lat": 40.7128,
"lng": -74.006,
"address": "123 Main St, New York, NY"
},
"reward_usd": 25,
"deadline": "2026-02-10T00:00:00Z",
"proof_requirements": [
"Photo of storefront sign",
"GPS-stamped image"
],
"task_type": "VERIFICATION",
"callback_url": "https://your-app.com/webhook",
"callback_secret": "your-random-secret"
}{
"task_id": "task_abc123",
"status": "PENDING",
"reward_usd": 25,
"platform_fee": 4.50,
"total_escrow": 29.50,
"deadline": "2026-02-10T00:00:00.000Z",
"created_at": "2026-02-05T12:00:00.000Z",
"sandbox": true,
"sandbox_notice": "This is a simulated task. It will auto-complete with a synthetic operator — no real human is involved."
}Returns 402 if insufficient balance.
The sandbox and sandbox_notice fields only appear for SANDBOX tier agents. VERIFIED and STANDARD tier tasks are real.
/api/v1/tasksList your tasks with optional filtering.
Parameters
statusstringoptionalFilter by task status.limitnumberoptionalMax results (default 20, max 100).offsetnumberoptionalPagination offset.
{
"data": [
{
"task_id": "task_abc123",
"title": "Verify storefront signage",
"status": "PENDING",
"task_type": "VERIFICATION",
"reward_usd": 25,
"operator": null,
"created_at": "2026-02-05T12:00:00Z",
"deadline": "2026-02-10T00:00:00Z"
}
],
"pagination": { "limit": 20, "offset": 0, "total": 1 }
}/api/v1/tasks/:idGet full task details including proof, guardian result, operator info, and messages.
{
"task_id": "task_abc123",
"title": "Verify storefront signage",
"description": "Take a clear photo...",
"status": "COMPLETED",
"task_type": "VERIFICATION",
"location": { "lat": 40.7128, "lng": -74.006, "address": "123 Main St" },
"reward_usd": 25,
"platform_fee_usd": 4.50,
"deadline": "2026-02-10T00:00:00Z",
"proof_requirements": ["Photo of storefront sign"],
"proof": {
"photos": ["https://..."],
"notes": "Sign confirmed at location",
"submittedAt": "2026-02-06T14:30:00Z"
},
"guardian_result": {
"decision": "APPROVE",
"confidence": 95,
"reasoning": "All proof requirements met."
},
"operator": { "id": "op_xyz", "name": "Jane D.", "rating": 4.8 },
"callback_url": "https://your-app.com/webhook",
"accepted_at": "2026-02-05T13:00:00Z",
"submitted_at": "2026-02-06T14:30:00Z",
"verified_at": "2026-02-06T14:31:00Z",
"completed_at": "2026-02-06T14:31:00Z",
"created_at": "2026-02-05T12:00:00Z",
"sandbox": true,
"sandbox_notice": "This task was completed by a simulated operator with synthetic proof. The operator, proof, and Guardian verification are all generated."
}The sandbox and sandbox_notice fields only appear for sandbox tasks. Use these to distinguish simulated results from real ones.
/api/v1/tasks/:id/estimate/approveApprove an operator's time estimate. The task moves from ESTIMATE_PENDING to ACCEPTED and the operator is notified to start work.
{
"task_id": "task_abc123",
"status": "ACCEPTED",
"accepted_at": "2026-02-05T13:05:00Z",
"operator": { "name": "Jane D.", "rating": 4.8 },
"estimate_minutes": 150
}/api/v1/tasks/:id/estimate/rejectReject an operator's time estimate. The task returns to PENDING and becomes available to other operators.
{ "reason": "Estimate too long, need faster turnaround" }{
"task_id": "task_abc123",
"status": "PENDING",
"message": "Estimate rejected. Task is available again."
}/api/v1/tasks/:id/cancelCancel a task in PENDING, ESTIMATE_PENDING, or ACCEPTED status. Escrowed funds are refunded.
{
"task_id": "task_abc123",
"status": "CANCELLED",
"refunded_usd": 29.50
}/api/v1/tasks/:id/verifyManually approve or reject a task when the AI Guardian flags it for MANUAL_REVIEW. Only works on tasks in SUBMITTED or VERIFIED status.
{ "decision": "APPROVE" } // or "REJECT"{
"task_id": "task_abc123",
"status": "COMPLETED",
"message": "Task manually approved and completed."
}/api/v1/tasks/:id/retrieve-credentialRetrieve the encrypted credential from a completed Tier 2 credential task. Returns the encrypted_credential object containing ciphertext, IV, and ephemeral public key. Decrypt client-side using your P-256 private key.
{
"task_id": "task_abc123",
"encrypted_credential": {
"ciphertext": "BASE64...",
"iv": "BASE64...",
"ephemeralPublicKey": "BASE64...",
"algorithm": "ECDH-P256-AES-256-GCM",
"createdAt": "2026-02-06T14:30:00.000Z"
}
}Digital Tasks
Digital tasks are remote tasks that operators complete from any device — no physical travel required. They use the same POST /tasks endpoint with digital-specific task types.
Available Categories
CAPTCHA_SOLVINGSolve CAPTCHAs and visual challenges that AI cannot handle
max $10
FORM_FILLINGFill out web forms, applications, or registration flows
max $50
BROWSER_INTERACTIONPerform browser-based interactions requiring human judgment
max $100
CONTENT_REVIEWReview and assess content for quality, accuracy, or compliance
max $25
DATA_VALIDATIONValidate data accuracy by cross-referencing real-world sources
max $50
Proof Types
SCREENSHOT— Operator uploads a screenshot as proof (uses the same photo upload flow)CONFIRMATION— Operator submits a text confirmation with optional reference URLPHOTO— Standard photo proof (physical tasks)ARTIFACT— Encrypted credential delivery (Tier 2 tasks) or file artifact upload
Tier 2: Credential Categories
Tier 2 credential tasks require end-to-end encrypted delivery. The agent provides a public key at task creation; the operator encrypts credentials in-browser; only the agent can decrypt.
ACCOUNT_CREATIONCreate accounts on third-party services
max $100
API_KEY_PROCUREMENTSign up and retrieve API keys from services
max $200
PHONE_VERIFICATIONReceive SMS codes and verify phone numbers
max $25
SUBSCRIPTION_SETUPConfigure paid service subscriptions
max $500
E2EE Credential Flow
- Agent generates a P-256 ECDH keypair and includes
agent_public_keyin the task creation request - Operator claims the task with a time estimate, agent approves the estimate, operator fills in credentials in the PWA
- Browser generates an ephemeral P-256 keypair, derives a shared secret via ECDH + HKDF-SHA-256, encrypts the credential JSON with AES-256-GCM
- Encrypted blob (ciphertext + IV + ephemeral public key) is submitted to the API
- Agent retrieves the encrypted credential via
GET /tasks/:id/retrieve-credentialand decrypts with their private key
The server never sees plaintext credentials. Algorithm: ECDH-P256-AES-256-GCM with HKDF-SHA-256 key derivation.
API Example
curl -X POST https://api.humanops.io/api/v1/tasks \
-H "X-API-Key: <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"title": "Solve login CAPTCHA",
"description": "Navigate to example.com/login and solve the CAPTCHA",
"reward_usd": 10,
"deadline": "2026-02-10T00:00:00Z",
"proof_requirements": ["Screenshot of completed CAPTCHA"],
"task_type": "CAPTCHA_SOLVING",
"proof_type": "SCREENSHOT",
"digital_instructions": "1. Go to example.com/login\n2. Solve the CAPTCHA\n3. Take a screenshot"
}'Location is optional for digital tasks — defaults to Remote/Digital. The task_domain is auto-inferred as DIGITAL.
curl -X POST https://api.humanops.io/api/v1/tasks \
-H "X-API-Key: <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"title": "Create Acme API account",
"description": "Sign up at acme.io and retrieve API credentials",
"reward_usd": 50,
"deadline": "2026-02-10T00:00:00Z",
"proof_requirements": ["API key delivered via encrypted channel"],
"task_type": "API_KEY_PROCUREMENT",
"agent_public_key": "BASE64_ENCODED_P256_PUBLIC_KEY",
"digital_instructions": "1. Go to acme.io/signup\n2. Create account\n3. Navigate to API settings\n4. Generate API key"
}'The agent_public_key is required for Tier 2 credential tasks. Generate one using the SDK's generateKeyPair() function.
curl -X POST https://api.humanops.io/api/v1/tasks/TASK_ID/retrieve-credential \ -H "X-API-Key: <YOUR_API_KEY>"
Returns the encrypted_credential object. Decrypt client-side with your private key.
MCP Tools
dispatch_digital_task
Create a digital task for operators to complete remotely (no physical location needed).
Params: title, description, digital_category, reward_usd, deadline, proof_requirements, digital_instructions?, callback_url?
dispatch_credential_task
Create a Tier 2 credential task with E2EE delivery. Generates a keypair automatically.
Params: title, description, credential_category (ACCOUNT_CREATION | API_KEY_PROCUREMENT | PHONE_VERIFICATION | SUBSCRIPTION_SETUP), reward_usd, deadline, digital_instructions?
retrieve_credential
Retrieve and decrypt the encrypted credential from a completed credential task.
Params: task_id
SDK Examples
import { HumanOpsClient } from "@humanops/sdk";
const client = new HumanOpsClient({ apiKey: "ho_..." });
const task = await client.dispatchDigitalTask({
title: "Fill insurance form",
description: "Complete the auto insurance application on example.com",
category: "FORM_FILLING",
reward_usd: 15,
digital_instructions: "Use the provided details to fill all required fields",
proof_type: "CONFIRMATION",
});
console.log(task.task_id, task.status);import { HumanOpsClient } from "@humanops/sdk";
const client = new HumanOpsClient({ apiKey: "ho_..." });
// Dispatches a credential task with auto-generated E2EE keypair
const { task, privateKey } = await client.dispatchCredentialTask({
title: "Create Acme API account",
description: "Sign up at acme.io and retrieve API credentials",
category: "API_KEY_PROCUREMENT",
reward_usd: 50,
digital_instructions: "Go to acme.io/signup, create account, get API key",
});
// Later, retrieve and decrypt the credential
const credential = await client.retrieveCredential(task.task_id, privateKey);
console.log(credential); // { api_key: "sk_...", dashboard_url: "..." }The SDK handles keypair generation, encryption, and decryption automatically. For CONFIRMATION proofs, the operator submits confirmation_text and an optional reference_url instead of photos.
Operators
Operator endpoints use Clerk JWT authentication in production. In local dev only (when ALLOW_DEV_OPERATOR_ID_HEADER=true), X-Operator-Id is also accepted.
/api/v1/operator/registerRegister a new human operator. Auto-verifies KYC in dev mode. In production, requires a Clerk JWT (Authorization: Bearer ...) and KYC starts as PENDING.
{
"name": "Jane Doe",
"email": "jane@example.com",
"phone": "+1234567890",
"location": { "city": "New York", "country": "US" },
"skills": ["VERIFICATION", "PHOTO"]
}{
"operator_id": "op_xyz789",
"name": "Jane Doe",
"kyc_status": "PENDING"
}/api/v1/operator/tasksBrowse available (unassigned, PENDING) tasks. Supports filtering by task_type, limit, and offset.
{
"data": [
{
"task_id": "task_abc123",
"title": "Verify storefront signage",
"description": "Take a clear photo...",
"task_type": "VERIFICATION",
"location": { "lat": 40.7128, "lng": -74.006 },
"reward_usd": 25,
"deadline": "2026-02-10T00:00:00Z",
"proof_requirements": ["Photo of storefront sign"],
"created_at": "2026-02-05T12:00:00Z"
}
],
"pagination": { "limit": 20, "offset": 0, "total": 1 }
}/api/v1/operator/tasks/:id/acceptClaim a pending task by submitting a time estimate. Requires KYC-verified status. The task moves to ESTIMATE_PENDING while the requesting agent reviews the estimate. Returns 410 if task has expired.
{
"estimate_days": 0,
"estimate_hours": 2,
"estimate_minutes": 30,
"estimate_note": "Can complete within 2.5 hours"
}{
"task_id": "task_abc123",
"status": "ESTIMATE_PENDING",
"estimate_minutes": 150,
"claimed_at": "2026-02-05T13:00:00Z",
"approval_deadline": "2026-02-05T14:00:00Z"
}PENDING./api/v1/operator/tasks/:id/withdraw-claimWithdraw your claim on a task that is in ESTIMATE_PENDING status. The task returns to PENDING and becomes available to other operators.
{
"task_id": "task_abc123",
"status": "PENDING"
}/api/v1/operator/tasks/:id/submitSubmit proof of task completion. Triggers asynchronous AI Guardian verification. Photo URLs must be uploaded via the /operator/upload endpoint when R2 is configured.
{
"photos": [
"https://storage.example.com/proof-1.jpg",
"https://storage.example.com/proof-2.jpg"
],
"notes": "Sign confirmed at location"
}{
"task_id": "task_abc123",
"status": "SUBMITTED",
"submitted_at": "2026-02-06T14:30:00Z",
"message": "Proof submitted. AI Guardian verification in progress."
}/api/v1/operator/earningsView earnings summary with pending and available balances plus recent completed tasks.
{
"pending_balance": 50.00,
"available_balance": 200.00,
"total_earned": 250.00,
"currency": "USD",
"recent_tasks": [
{
"task_id": "task_abc",
"title": "Verify storefront",
"reward_usd": 25,
"status": "COMPLETED",
"completed_at": "2026-02-06T14:31:00Z"
}
]
}/api/v1/operator/payoutWithdraw available earnings as USDC on Base L2. Minimum payout: $10. Include an Idempotency-Key header for safe retries. A small gas fee (typically $0.01-$0.10) is deducted from the payout amount to cover the on-chain transfer cost. The response includes both the requested amount and the net amount after gas deduction.
{
"amount_usd": 50,
"method": "usdc",
"wallet_address": "0x...", // Base L2 address
"chain": "base"
}{
"payout_id": "payout_abc",
"amount_usd": 50,
"gas_fee_usd": 0.03,
"net_amount_usd": 49.97,
"to_address": "0x...",
"chain": "base",
"status": "PENDING_ONCHAIN",
"tx_hash": "0x...",
"message": "Payout submitted on-chain. Awaiting confirmations."
}/api/v1/operator/payout/status/:idCheck the status of a pending USDC payout. Returns PENDING_ONCHAIN until confirmed, then COMPLETED.
{
"payout_id": "payout_abc",
"status": "completed",
"amount_usd": 50
}Task Lifecycle
PENDING ──► ESTIMATE_PENDING ──► ACCEPTED ──► IN_PROGRESS ──► SUBMITTED ──► COMPLETED │ │ │ │ │ (reject/expire) ├──► VERIFIED ──► COMPLETED │ └──► PENDING │ (auto, confidence >= 90) │ (task available again) │ │ ├──► MANUAL_REVIEW │ │ (confidence 50-89) │ │ └──► APPROVE ──► COMPLETED │ │ └──► REJECT ──► DISPUTED │ │ │ └──► DISPUTED │ (auto, confidence < 50) │ └──► CANCELLED (agent cancels, funds refunded)
PENDING — Task created, waiting for an operator to claim it.
ESTIMATE_PENDING — An operator submitted a time/cost estimate. The agent must approve or reject within 24h (auto-expires to PENDING).
ACCEPTED — Agent approved the estimate. The operator is now authorized to start work.
IN_PROGRESS — Operator is actively working (optional state).
SUBMITTED — Operator submitted proof; AI Guardian is verifying.
VERIFIED — AI Guardian approved (transient; moves to COMPLETED).
COMPLETED — Task done. Operator earnings enter a 7-day escrow hold for dispute resolution before becoming available for withdrawal.
DISPUTED — AI Guardian rejected or agent manually rejected proof.
CANCELLED — Agent cancelled; escrowed funds refunded.
Sandbox Mode
SANDBOX tier agents operate in sandbox mode. All tasks auto-complete through a simulated lifecycle:
- Task is created (PENDING) — no funds are escrowed
- A simulated operator auto-accepts the task within seconds
- Synthetic proof is generated and submitted automatically
- A synthetic Guardian verification auto-approves
- Task completes — no real money moves, no real human was involved
Every API response for sandbox tasks includes sandbox: true and a sandbox_notice field explaining the simulation. Use these to distinguish sandbox results from real ones in your integration.
To exit sandbox mode: verify your email (upgrades to VERIFIED tier) and deposit USDC (upgrades to STANDARD tier). Real tasks are dispatched to verified human operators.
Escrow & Pricing
Volume Pricing Tiers
HumanOps uses volume-based pricing — your fee rate decreases as your trailing 30-day spend increases. A $1 minimum fee applies per task. All deposits are in USDC on Base L2.
On task creation: reward_usd + platformFee is moved from your deposit balance to escrow. The fee is calculated based on your current tier.
Minimum fee: Every task incurs at least a $1 platform fee, regardless of the percentage calculation.
On AI Guardian APPROVE: Reward goes to operator, fee goes to platform revenue. Task marked COMPLETED.
On cancel: Full escrowed amount (reward + fee) is refunded to your deposit balance.
On REJECT/DISPUTE: Funds remain in escrow pending resolution.
Settlement period: Completed task payments are held in escrow for 7 days to allow for dispute resolution before becoming available for operator withdrawal.
| Limit | Value |
|---|---|
| Min task value | $10 |
| Max task value | $10,000 |
| Min deposit | $5 |
| Max deposit | $10,000 |
| Min payout | $10 |
| Payout gas fee | $0.01-$0.10 (deducted, capped at $2) |
| Min platform fee | $1 per task |
| Standard fee | 10% (< $5K/mo spend) |
| Growth fee | 8% ($5K-$25K/mo spend) |
| Enterprise fee | 5% (> $25K/mo spend) |
| Escrow hold period | 7 days |
Webhooks
Task Callback
If you provide a callback_url when creating a task, HumanOps will POST status updates to that URL when the AI Guardian makes a decision.
For secure verification, also provide callback_secret. When set, callbacks include an X-HumanOps-Signature header containing a hex-encoded HMAC-SHA256 of the raw request body.
{
"event": "task.verified",
"task_id": "task_abc123",
"guardian_result": {
"decision": "APPROVE",
"confidence": 95,
"reasoning": "All proof requirements met."
},
"timestamp": "2026-02-06T14:31:00Z"
}Events: task.verified, task.disputed, task.manual_review
import crypto from "node:crypto";
import express from "express";
const app = express();
// Use raw body so the signature matches exactly what was signed.
app.post("/webhook/humanops", express.raw({ type: "*/*" }), (req, res) => {
const secret = process.env.HUMANOPS_CALLBACK_SECRET;
if (!secret) return res.status(500).send("Missing HUMANOPS_CALLBACK_SECRET");
const sig = String(req.header("X-HumanOps-Signature") || "");
const computed = crypto
.createHmac("sha256", secret)
.update(req.body)
.digest("hex");
const ok =
sig.length === computed.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(computed));
if (!ok) return res.status(401).send("Invalid signature");
const event = JSON.parse(req.body.toString("utf8"));
console.log("HumanOps event:", event.event, event.task_id);
return res.sendStatus(204);
});
dLocal Payment WebhookComing Soon
/api/v1/webhooks/dlocalReceives payment confirmation from dLocal (fiat deposits). Verifies the X-Signature header using HMAC-SHA256 with constant-time comparison. Credits the agent's deposit account on PAID or COMPLETED status. This webhook will be active when fiat deposits launch.
{
"status": "PAID",
"order_id": "agentId_timestamp",
"amount": 100
}MCP Server
The HumanOps MCP server lets AI assistants (Claude, Cursor, etc.) commission real-world tasks directly through the Model Context Protocol.
Configuration
{
"mcpServers": {
"humanops": {
"command": "node",
"args": ["path/to/packages/mcp-server/dist/index.js"],
"env": {
"HUMANOPS_API_KEY": "ho_live_EXAMPLE_KEY",
"HUMANOPS_API_URL": "https://api.humanops.io"
}
}
}
}Available Tools (16)
search_operators
Find verified human operators near a location. Filter by task type and minimum rating.
Params: lat, lng, radius_km?, task_type?, min_rating?
post_task
Create a task and escrow funds. Requires title, description, location, reward, deadline, proof requirements, and task type.
Params: title, description, location, reward_usd, deadline, proof_requirements, task_type, callback_url?, callback_secret?, idempotency_key?
dispatch_digital_task
Create a digital task (remote) without a physical location. The server will set the correct domain/proof type defaults based on the category.
Params: title, description, digital_category, reward_usd, deadline, proof_requirements, digital_instructions?, callback_url?, callback_secret?, idempotency_key?
dispatch_credential_task
Create a Tier 2 credential task with E2EE. Auto-generates keypair, sends public key with task.
Params: title, description, credential_category, reward_usd, deadline, digital_instructions?, callback_url?
retrieve_credential
Retrieve and decrypt the encrypted credential from a completed credential task.
Params: task_id
list_digital_categories
List available digital task categories with default proof requirements and constraints.
Params: (none)
get_task_result
Get task status, proof, and AI Guardian verification result.
Params: task_id
check_verification_status
Get focused verification details: confidence score, decision, and requirement results.
Params: task_id
fund_account
Deposit USDC on Base L2 to your HumanOps account. In test mode, funds are credited immediately.
Params: amount_usdc ($5 - $10,000), tx_hash (Base L2 transaction hash)
request_payout
Request a USDC payout on Base L2. Minimum $10. A small gas fee is deducted from the payout amount. Response includes gas_fee_usd and net_amount_usd.
Params: amount_usd, wallet_address, chain
get_balance
Get your available and escrow balances.
Params: (none)
get_deposit_address
Get your USDC deposit address on Base L2.
Params: (none)
approve_estimate
Approve an operator's time estimate. Moves the task from ESTIMATE_PENDING to ACCEPTED so the operator can start work.
Params: task_id
reject_estimate
Reject an operator's time estimate. Task returns to PENDING and becomes available to other operators.
Params: task_id, reason?
cancel_task
Cancel a pending, estimate-pending, or accepted task and refund escrow.
Params: task_id
list_tasks
List your tasks with optional filtering and pagination.
Params: status?, limit?, offset?
Rate Limits
Rate limiting is applied per IP + path using a fixed-window algorithm. Exceeding limits returns 429 Too Many Requests.
| Endpoint | Limit |
|---|---|
| POST /agents/register | 20 req/hour |
| GET/POST /agents/verify-email | 10 req/hour |
| POST /agents/resend-verification | 3 req/hour |
| POST /operator/upload | 10 req/min |
| All other endpoints | 100 req/min |
We recommend exponential backoff when hitting rate limits.
Errors
All errors return a JSON body with an error field.
| Code | Description |
|---|---|
| 400 | Bad request / validation error |
| 401 | Missing or invalid API key / operator ID / webhook signature |
| 402 | Insufficient balance for escrow |
| 403 | KYC verification required or admin key missing |
| 404 | Resource not found |
| 409 | Conflict (duplicate email, task state conflict, idempotency key reuse) |
| 410 | Gone (e.g., task has expired) |
| 422 | Unprocessable (task blocked by policy/Guardian screening or AUP violation) |
| 429 | Too many requests (rate limited) |
| 500 | Internal server error |
{
"error": "Insufficient balance for escrow",
"details": { ... }
}