Quick start
Three steps to your first verification.
1
Get your API key
Sign up at haaa.dev. Your key is available immediately — no credit card required.
2
Run your first verification
curl -X POST https://api.haaa.dev/verify \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "task": "Is this message professional enough to send to a client?", "content": "Hey, just checking in on that thing we discussed." }'
3
Handle the response
A verdict of approve means the validator confirmed it. A verdict of reject means it came back with a rejection_reason — use that to fix and retry, or route to a fallback.
// Example response { "task_id": "a3f9d1c2-8b4e-4f2a-9c1d-7e6f5a4b3c2d", "verdict": "approve", "confidence": 0.94, "consensus": "1/1", "time_ms": 28400, "rejection_reason": null, "worker_ids": ["anon_a1b2c3"] }
Authentication
Every request requires an API key passed as a Bearer token in the Authorization header.
Authorization: Bearer YOUR_API_KEY
API keys are scoped to your account. Do not expose them in client-side code or public repositories. Get your key at haaa.dev.
POST /verify
Submit a task for human verification. Returns a structured response once a validator completes the review — or the Ghost Agent handles fallback if no human claims within 90 seconds.
POST
https://api.haaa.dev/verify
Sync · ~60s p50
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| task | string | required | Plain-language instruction for the validator. Keep it a yes/no or approve/reject question. Max 500 characters. |
| content | string | required | The agent output to be reviewed. PII is stripped automatically before any human sees it. Max 3,000 characters. Chunk longer content before calling /verify. |
| context | string | optional | Additional background the validator needs. Max 500 characters. |
| consensus | boolean | optional | Request two-human consensus verification with automatic tiebreaker. Default: false. |
Example request
curl -X POST https://api.haaa.dev/verify \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "task": "Is this email appropriate to send to a client?", "content": "Hi John, following up on the invoice from last month...", "context": "Client is a senior executive. Formal tone required.", "consensus": false }'
import requests response = requests.post( "https://api.haaa.dev/verify", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "task": "Is this email appropriate to send to a client?", "content": agent_output, "context": "Formal tone required.", "consensus": False } ) result = response.json() if result["verdict"] == "reject": handle_rejection(result["rejection_reason"]) elif result["confidence"] < 0.85: escalate_for_review(result) else: proceed_with_output()
const response = await fetch("https://api.haaa.dev/verify", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json", }, body: JSON.stringify({ task: "Is this email appropriate to send to a client?", content: agentOutput, context: "Formal tone required.", consensus: false, }), }); const result = await response.json(); if (result.verdict === "reject") { handleRejection(result.rejection_reason); } else if (result.confidence < 0.85) { escalateForReview(result); } else { proceedWithOutput(); }
// HTTP Request node configuration { "method": "POST", "url": "https://api.haaa.dev/verify", "authentication": "headerAuth", "body": { "task": "{{ $json.task_description }}", "content": "{{ $json.agent_output }}", "context": "{{ $json.context }}", "consensus": false } }
Response
200 OK
application/json
{
"task_id": "a3f9d1c2-8b4e-4f2a-9c1d-7e6f5a4b3c2d",
"verdict": "approve", // "approve" | "reject"
"confidence": 0.94, // 0.0 – 1.0
"consensus": "1/1", // "1/1" | "2/2" | "ghost_agent"
"time_ms": 28400,
"rejection_reason": null, // string if rejected
"worker_ids": ["anon_a1b2c3"]
}
confidence is calculated from consensus count, worker reputation, and time-to-decision. Build conditional logic on it:
if confidence < 0.85, escalate. When consensus is "ghost_agent", the AI fallback handled the task — no human was available within 90 seconds.
Response schema
| Field | Type | Description |
|---|---|---|
| task_id | string | UUID for this verification task. |
| verdict | string | approve or reject. |
| confidence | float | 0.0–1.0. Composite of consensus count, worker reputation, and time-to-decision. Use to build conditional escalation logic. |
| consensus | string | 1/1, 2/2, or ghost_agent. Ghost agent activates at 90s if no human claims the task. |
| time_ms | integer | Total elapsed time in milliseconds from request to response. Monitor against your SLA. |
| rejection_reason | string | null | Human-provided reason when verdict is reject. Null on approve. |
| worker_ids | array | Anonymised validator identifiers. Empty array when ghost agent handled. |
Error codes
HaaA uses standard HTTP status codes. All error responses follow this shape:
{
"error": {
"code": "insufficient_credits",
"message": "Your account has 0 credits remaining. Add credits at haaa.dev."
}
}
| Status | Code | Description |
|---|---|---|
| 200 | ok |
Verification complete. Check the verdict field. |
| 400 | bad_request |
task or content field missing or exceeds character limit. |
| 401 | unauthorized |
Invalid or missing API key. |
| 402 | insufficient_credits |
Account has no credits remaining. Top up at haaa.dev. |
| 422 | pii_blocked |
Content flagged by PII filter and could not be sanitised. Revise and retry. |
| 429 | rate_limited |
Rate limit exceeded. See rate limits. |
| 503 | unavailable |
No validators available and Ghost Agent fallback also unavailable. Rare. Retry after 30s. |
Rate limits
Free
5
req / min
2 concurrent
Starter
20
req / min
5 concurrent
Agency Pro
60
req / min
20 concurrent
Enterprise
∞
unlimited
unlimited
Rate limit headers are included in every response:
X-RateLimit-Limit: 60 X-RateLimit-Remaining: 47 X-RateLimit-Reset: 1709123456
SLA note: HaaA targets sub-60s response time for all human verifications. If no validator claims within 90 seconds, the Ghost Agent (AI fallback) handles the task automatically. The
consensus field will read "ghost_agent" in this case. Ghost Agent responses consume credits at the standard rate.