> ## Documentation Index
> Fetch the complete documentation index at: https://docs.humancheck.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# REST API Integration

> Universal HTTP integration for any framework or language

The REST API is the most universal way to integrate Humancheck with any AI agent, regardless of framework or language. It provides a simple HTTP interface for creating reviews, checking status, and retrieving decisions.

## Base URL

The base URL depends on which Humancheck product you're using:

### Platform (Cloud)

```
https://api.humancheck.dev
```

<Card title="Using Platform?" icon="cloud" href="/platform/overview">
  Managed cloud service with production-scale infrastructure. Get started in minutes with no setup required.
</Card>

### Open Source (Self-Hosted)

```
http://localhost:8000  # Local development
https://your-domain.com  # Production deployment
```

<Card title="Using Open Source?" icon="code" href="/open-source/overview">
  Self-host the Humancheck stack for full control over data, deployment, and customization.
</Card>

## Authentication

### Platform

All API requests require authentication using an API key. Include your API key in the `Authorization` header:

```python theme={null}
headers = {
    "Authorization": "Bearer your-api-key-here",
    "Content-Type": "application/json"
}
```

<Tip>
  Get your API key from [platform.humancheck.dev](https://platform.humancheck.dev) under your organization settings.
</Tip>

### Open Source

Authentication is optional. By default, the API is open. You can enable authentication in `humancheck.yaml`:

```yaml theme={null}
enable_auth: true
api_key: your-secret-api-key
```

When enabled, include the API key in the `Authorization` header as shown above.

## Creating a Review

### Basic Review Request

<Tabs>
  <Tab title="Platform">
    ```python theme={null}
    import httpx

    async with httpx.AsyncClient() as client:
        response = await client.post(
            "https://api.humancheck.dev/reviews",
            headers={
                "Authorization": "Bearer your-api-key-here",
                "Content-Type": "application/json"
            },
            json={
                "task_type": "payment",
                "proposed_action": "Process payment of $5,000 to ACME Corp",
                "agent_reasoning": "Payment exceeds auto-approval limit",
                "confidence_score": 0.85,
                "urgency": "high",
                "blocking": False
            }
        )
        review = response.json()
        print(f"Review ID: {review['id']}")
    ```
  </Tab>

  <Tab title="Open Source">
    ```python theme={null}
    import httpx

    async with httpx.AsyncClient() as client:
        response = await client.post(
            "http://localhost:8000/reviews",  # Your self-hosted URL
            json={
                "task_type": "payment",
                "proposed_action": "Process payment of $5,000 to ACME Corp",
                "agent_reasoning": "Payment exceeds auto-approval limit",
                "confidence_score": 0.85,
                "urgency": "high",
                "blocking": False
            }
        )
        review = response.json()
        print(f"Review ID: {review['id']}")
    ```
  </Tab>
</Tabs>

### Blocking Request

Wait for the decision before proceeding:

```python theme={null}
response = await client.post(
    "https://api.humancheck.dev/reviews",
    headers={
        "Authorization": "Bearer your-api-key-here",
        "Content-Type": "application/json"
    },
    json={
        "task_type": "payment",
        "proposed_action": "Process payment of $5,000",
        "agent_reasoning": "High-value payment",
        "confidence_score": 0.85,
        "urgency": "high",
        "blocking": True  # Wait for decision
    }
)
review = response.json()

# Decision is included in the response
if review.get("decision"):
    decision = review["decision"]
    if decision["decision_type"] == "approve":
        process_payment()
```

## Review Fields

| Field              | Type    | Required | Description                                        |
| ------------------ | ------- | -------- | -------------------------------------------------- |
| `task_type`        | string  | Yes      | Type of task (e.g., "payment", "data\_deletion")   |
| `proposed_action`  | string  | Yes      | The action to be reviewed                          |
| `agent_reasoning`  | string  | No       | Why the agent is requesting review                 |
| `confidence_score` | float   | No       | Confidence score (0.0-1.0)                         |
| `urgency`          | string  | No       | Urgency level: "low", "medium", "high", "critical" |
| `framework`        | string  | No       | Framework identifier (e.g., "langchain", "custom") |
| `metadata`         | object  | No       | Custom metadata object                             |
| `organization_id`  | integer | No       | Organization ID for multi-tenancy                  |
| `agent_id`         | integer | No       | Registered agent ID                                |
| `blocking`         | boolean | No       | Wait for decision (default: false)                 |

## Checking Review Status

### Get Review Details

```python theme={null}
response = await client.get(
    f"https://api.humancheck.dev/reviews/{review_id}",
    headers={"Authorization": "Bearer your-api-key-here"}
)
review = response.json()

print(f"Status: {review['status']}")
print(f"Task Type: {review['task_type']}")
print(f"Proposed Action: {review['proposed_action']}")
```

### List Reviews

```python theme={null}
# List all reviews
response = await client.get(
    "https://api.humancheck.dev/reviews",
    headers={"Authorization": "Bearer your-api-key-here"}
)
reviews = response.json()

# Filter by status
response = await client.get(
    "https://api.humancheck.dev/reviews",
    params={"status": "pending"}
)

# Filter by task type
response = await client.get(
    "https://api.humancheck.dev/reviews",
    params={"task_type": "payment"}
)

# Pagination
response = await client.get(
    "https://api.humancheck.dev/reviews",
    params={"page": 1, "page_size": 20}
)
```

## Getting Decisions

### Check for Decision

```python theme={null}
response = await client.get(
    f"https://api.humancheck.dev/reviews/{review_id}/decision",
    headers={"Authorization": "Bearer your-api-key-here"}
)
decision = response.json()

if decision:
    print(f"Decision: {decision['decision_type']}")
    if decision["decision_type"] == "approve":
        print("✅ Approved")
    elif decision["decision_type"] == "reject":
        print(f"❌ Rejected: {decision.get('notes')}")
    elif decision["decision_type"] == "modify":
        print(f"✏️ Modified: {decision['modified_action']}")
else:
    print("⏳ Still pending")
```

### Polling for Decision

```python theme={null}
import asyncio

async def wait_for_decision(review_id, timeout=300, poll_interval=5):
    """Poll for decision with timeout."""
    async with httpx.AsyncClient() as client:
        start_time = asyncio.get_event_loop().time()
        
        while True:
            elapsed = asyncio.get_event_loop().time() - start_time
            if elapsed > timeout:
                raise TimeoutError("Decision timeout")
            
            response = await client.get(
                f"https://api.humancheck.dev/reviews/{review_id}/decision"
            )
            decision = response.json()
            
            if decision:
                return decision
            
            await asyncio.sleep(poll_interval)

# Usage
decision = await wait_for_decision(review_id, timeout=300)
```

## Making Decisions (from Dashboard or API)

### Approve a Review

```python theme={null}
response = await client.post(
    f"https://api.humancheck.dev/reviews/{review_id}/decide",
    json={
        "reviewer_id": 1,  # User ID
        "decision_type": "approve",
        "notes": "Payment approved"
    }
)
```

### Reject a Review

```python theme={null}
response = await client.post(
    f"https://api.humancheck.dev/reviews/{review_id}/decide",
    json={
        "reviewer_id": 1,
        "decision_type": "reject",
        "notes": "Vendor not verified"
    }
)
```

### Modify a Review

```python theme={null}
response = await client.post(
    f"https://api.humancheck.dev/reviews/{review_id}/decide",
    json={
        "reviewer_id": 1,
        "decision_type": "modify",
        "modified_action": "Process payment of $4,500 to ACME Corp",
        "notes": "Reduced amount per policy"
    }
)
```

## Submitting Feedback

```python theme={null}
response = await client.post(
    f"https://api.humancheck.dev/reviews/{review_id}/feedback",
    headers={
        "Authorization": "Bearer your-api-key-here",
        "Content-Type": "application/json"
    },
    json={
        "rating": 5,  # 1-5 scale
        "comment": "Quick and clear decision, thank you!"
    }
)
```

## Error Handling

```python theme={null}
try:
    response = await client.post(
        "https://api.humancheck.dev/reviews",
        json={...}
    )
    response.raise_for_status()
    review = response.json()
except httpx.HTTPStatusError as e:
    if e.response.status_code == 400:
        print("Bad request:", e.response.json())
    elif e.response.status_code == 404:
        print("Review not found")
    elif e.response.status_code == 408:
        print("Request timed out waiting for decision")
    else:
        print(f"Error: {e.response.status_code}")
```

## Complete Example

```python theme={null}
import httpx
import asyncio

async def payment_workflow(amount, vendor):
    """Example workflow for payment approval."""
    async with httpx.AsyncClient() as client:
        # Create review
        response = await client.post(
            "https://api.humancheck.dev/reviews",
            headers={
                "Authorization": "Bearer your-api-key-here",
                "Content-Type": "application/json"
            },
            json={
                "task_type": "payment",
                "proposed_action": f"Process payment of ${amount} to {vendor}",
                "agent_reasoning": f"Payment amount (${amount}) exceeds auto-approval limit",
                "confidence_score": 0.85,
                "urgency": "high" if amount > 5000 else "medium",
                "blocking": True  # Wait for decision
            }
        )
        review = response.json()
        
        # Check if decision is ready
        if review.get("decision"):
            decision = review["decision"]
        else:
            # Poll for decision
            decision = await wait_for_decision(review["id"])
        
        # Process based on decision
        if decision["decision_type"] == "approve":
            process_payment(amount, vendor)
        elif decision["decision_type"] == "modify":
            # Extract amount from modified action
            modified_action = decision["modified_action"]
            process_payment_from_action(modified_action)
        else:
            print("Payment rejected")
            return None

asyncio.run(payment_workflow(5000, "ACME Corp"))
```

## Using with cURL

### Create Review

```bash theme={null}
curl -X POST https://api.humancheck.dev/reviews \
  -H "Authorization: Bearer your-api-key-here" \
  -H "Content-Type: application/json" \
  -d '{
    "task_type": "payment",
    "proposed_action": "Process payment of $5,000",
    "agent_reasoning": "High-value payment",
    "confidence_score": 0.85,
    "urgency": "high"
  }'
```

### Get Review

```bash theme={null}
curl https://api.humancheck.dev/reviews/1 \
  -H "Authorization: Bearer your-api-key-here"
```

### Get Decision

```bash theme={null}
curl https://api.humancheck.dev/reviews/1/decision \
  -H "Authorization: Bearer your-api-key-here"
```

## Next Steps

* Learn about [MCP Integration](/integrations/mcp) for Claude Desktop
* Explore [LangChain Integration](/integrations/langchain) for LangChain/LangGraph agents
* Check out [Use Cases](/use-cases/payment-approval) for real-world examples
