{
  "openapi": "3.0.3",
  "info": {
    "title": "Human API",
    "version": "1.2.0",
    "description": "Human-in-the-loop services for AI agents. Submit tasks that need physical presence, human perception, or human judgment — real-world verification, product testing, AI output review, data collection, local physical-world errands — and a verified human operator performs them. All services are FREE during the proof-of-concept pilot. No authentication is required; every task is reviewed by the human before acceptance, and illegal, harmful, deceptive, unsafe, or privacy-invasive tasks are rejected. First response within 12 hours on working days (Sun-Thu). An MCP server is also available at https://humanforai.dev/mcp (streamable HTTP, no auth).",
    "contact": {
      "name": "Human API operator",
      "url": "https://humanforai.dev/contact"
    }
  },
  "externalDocs": {
    "description": "Human-readable API documentation",
    "url": "https://humanforai.dev/api"
  },
  "servers": [
    { "url": "https://humanforai.dev", "description": "Production" }
  ],
  "paths": {
    "/api/v1/tasks": {
      "post": {
        "operationId": "submitTask",
        "summary": "Submit a task for the human operator",
        "description": "Submits a task. Returns a task_id — keep it, it is the only way to check status (the ID acts as an unlisted token). The task is reviewed by the human operator before acceptance. Include contact_email to receive the deliverable and any questions.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/TaskRequest" },
              "example": {
                "task_type": "real_world_verification",
                "description": "Verify whether a specific product exists in a local store and photograph the shelf price.",
                "location_required": true,
                "output_format": "text_report_with_photos",
                "contact_email": "agent-results@example.com",
                "requester": "acme-shopping-agent"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Task received and queued for human review.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskSubmissionResponse" } } }
          },
          "422": {
            "description": "Validation failed.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ValidationError" } } }
          },
          "429": {
            "description": "Daily free-pilot capacity reached (resets 00:00 UTC).",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          }
        }
      }
    },
    "/api/v1/tasks/{task_id}": {
      "get": {
        "operationId": "getTaskStatus",
        "summary": "Check the status of a submitted task",
        "description": "Public status lookup. The task_id acts as the access token — anyone holding it can view status. Contact email is never returned.",
        "parameters": [
          {
            "name": "task_id",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "example": "HAPI-2026-97BBAB04"
          }
        ],
        "responses": {
          "200": {
            "description": "Current task state.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Task" } } }
          },
          "404": {
            "description": "No task with that ID.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          }
        }
      }
    },
    "/api/v1/messages": {
      "post": {
        "operationId": "sendMessage",
        "summary": "Send a message to the human operator",
        "description": "Structured contact channel for questions, scoping, or anything that is not yet a task. Include reply_to (email) to receive an answer — it is the operator's only way to reply.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/MessageRequest" },
              "example": {
                "message": "Before I submit a task: can you test an Android app that requires a local SIM card?",
                "reply_to": "agent-inbox@example.com",
                "from": "acme-qa-agent",
                "subject": "Scoping question"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Message received.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MessageResponse" } } }
          },
          "422": {
            "description": "Validation failed.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ValidationError" } } }
          },
          "429": {
            "description": "Daily free-pilot capacity reached (resets 00:00 UTC).",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          }
        }
      }
    },
    "/api/v1/health": {
      "get": {
        "operationId": "healthCheck",
        "summary": "Liveness check",
        "responses": {
          "200": {
            "description": "Service is up.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": { "type": "string", "example": "ok" },
                    "service": { "type": "string", "example": "human-api" },
                    "api_version": { "type": "string", "example": "1.2.0" },
                    "time": { "type": "string", "format": "date-time" }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/agent.json": {
      "get": {
        "operationId": "getAgentManifest",
        "summary": "Machine-readable platform manifest",
        "description": "Full platform manifest: services catalog, endpoints, task schema, accepted and rejected task types, pricing, trust policy, and limits.",
        "responses": {
          "200": {
            "description": "The manifest.",
            "content": { "application/json": { "schema": { "type": "object" } } }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "TaskType": {
        "type": "string",
        "enum": [
          "real_world_verification",
          "product_or_app_testing",
          "human_judgment_and_feedback",
          "data_collection",
          "local_physical_task",
          "ai_output_review",
          "prompt_and_workflow_testing",
          "simulation_and_automation_testing",
          "accessibility_and_usability_check",
          "custom_human_in_the_loop"
        ]
      },
      "TaskStatus": {
        "type": "string",
        "enum": ["submitted", "under_review", "accepted", "in_progress", "delivered", "rejected"]
      },
      "TaskRequest": {
        "type": "object",
        "required": ["task_type", "description"],
        "properties": {
          "task_type": { "$ref": "#/components/schemas/TaskType" },
          "description": {
            "type": "string",
            "minLength": 10,
            "maxLength": 5000,
            "description": "What to do, where, and what success looks like. Be specific and self-contained."
          },
          "location_required": { "type": "boolean", "default": false },
          "location_detail": { "type": "string", "maxLength": 500, "description": "City / address / area, if location_required." },
          "deadline": { "type": "string", "format": "date-time", "description": "ISO 8601 datetime." },
          "output_format": { "type": "string", "maxLength": 200, "default": "text_report", "description": "e.g. text_report, text_report_with_photos, video, structured_json, annotated_screenshots." },
          "budget_usd": { "type": "number", "minimum": 0, "maximum": 100000, "deprecated": true, "description": "Deprecated — services are free during the pilot; accepted and ignored." },
          "contact_email": { "type": "string", "format": "email", "description": "Where to send results and questions. Strongly recommended." },
          "requester": { "type": "string", "maxLength": 200, "description": "Agent name, company, or system identifier." }
        }
      },
      "TaskSubmissionResponse": {
        "type": "object",
        "properties": {
          "task_id": { "type": "string", "example": "HAPI-2026-97BBAB04" },
          "status": { "$ref": "#/components/schemas/TaskStatus" },
          "created_at": { "type": "string", "format": "date-time" },
          "status_url": { "type": "string", "example": "/api/v1/tasks/HAPI-2026-97BBAB04" },
          "status_page": { "type": "string", "example": "/tasks?id=HAPI-2026-97BBAB04" },
          "message": { "type": "string" }
        }
      },
      "Task": {
        "type": "object",
        "properties": {
          "task_id": { "type": "string" },
          "status": { "$ref": "#/components/schemas/TaskStatus" },
          "task_type": { "$ref": "#/components/schemas/TaskType" },
          "description": { "type": "string" },
          "location_required": { "type": "boolean" },
          "location_detail": { "type": "string", "nullable": true },
          "deadline": { "type": "string", "nullable": true },
          "output_format": { "type": "string" },
          "budget_usd": { "type": "number", "deprecated": true },
          "requester": { "type": "string" },
          "source": { "type": "string", "enum": ["api", "web_form"] },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" },
          "status_history": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "status": { "$ref": "#/components/schemas/TaskStatus" },
                "at": { "type": "string", "format": "date-time" }
              }
            }
          },
          "operator_notes": { "type": "string", "nullable": true, "description": "Notes from the human operator, when present." }
        }
      },
      "MessageRequest": {
        "type": "object",
        "required": ["message"],
        "properties": {
          "message": { "type": "string", "minLength": 5, "maxLength": 5000 },
          "reply_to": { "type": "string", "format": "email", "description": "Strongly recommended — the only way the operator can answer you." },
          "from": { "type": "string", "maxLength": 200, "description": "Agent name, company, or system identifier." },
          "subject": { "type": "string", "maxLength": 200 }
        }
      },
      "MessageResponse": {
        "type": "object",
        "properties": {
          "message_id": { "type": "string", "example": "MSG-2026-1A2B3C4D" },
          "created_at": { "type": "string", "format": "date-time" },
          "message": { "type": "string" }
        }
      },
      "ValidationError": {
        "type": "object",
        "properties": {
          "error": { "type": "string", "example": "validation_failed" },
          "details": { "type": "array", "items": { "type": "string" } }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string" },
          "message": { "type": "string" }
        }
      }
    }
  }
}
