Examples
Sample code and common use cases.
Use cases
AI Agent Refunds
Your AI agent identifies a customer who should get a refund, but you want human approval first.
import requests
def request_refund_approval(customer_id, amount, reason):
response = requests.post(
'https://humanapproval.dev/api/v1/requests',
headers={'Authorization': f'Bearer {API_KEY}'},
json={
'title': f'Approve ${amount/100} refund for customer #{customer_id}',
'external_id': f'refund-{customer_id}-{timestamp}',
'payload': {
'customer_id': customer_id,
'amount': amount,
'reason': reason,
'account_balance': get_balance(customer_id)
}
}
)
return response.json()['id']
Infrastructure Spending
Require approval before provisioning expensive cloud resources.
async function requestInfraApproval(instanceType, count) {
const response = await fetch('https://humanapproval.dev/api/v1/requests', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.APPROVAL_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
title: `Provision ${count}x ${instanceType} instances`,
payload: {
instance_type: instanceType,
count: count,
estimated_cost: calculateCost(instanceType, count),
region: 'us-east-1'
},
expires_at: new Date(Date.now() + 30 * 60 * 1000).toISOString() // 30 min expiry
})
});
return await response.json();
}
Production Deployments
Gate production deployments with manual approval.
#!/bin/bash
# deploy.sh
# Submit deployment for approval
REQUEST_ID=$(curl -X POST https://humanapproval.dev/api/v1/requests \
-H "Authorization: Bearer $APPROVAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Deploy v2.1.0 to production",
"payload": {
"version": "v2.1.0",
"commit": "abc123",
"changed_files": 42,
"tests_passed": true
}
}' | jq -r '.id')
echo "Waiting for approval: $REQUEST_ID"
# Poll for decision (or use webhooks in real implementation)
while true; do
STATUS=$(curl -s https://humanapproval.dev/api/v1/requests/$REQUEST_ID \
-H "Authorization: Bearer $APPROVAL_API_KEY" \
| jq -r '.status')
if [ "$STATUS" = "approved" ]; then
echo "Approved! Deploying..."
./deploy-to-production.sh
break
elif [ "$STATUS" = "rejected" ]; then
echo "Deployment rejected"
exit 1
fi
sleep 5
done
Python SDK (Coming Soon)
We’re working on an official Python SDK:
from human_approval import Client
client = Client(api_key='your_api_key')
# Submit request
request = client.requests.create(
title='Approve $500 refund',
payload={'customer_id': 'cust_123', 'amount': 500}
)
# Wait for decision (blocking)
decision = request.wait_for_decision(timeout=300) # 5 minutes
if decision.approved:
process_refund(decision.payload)
else:
log_rejection(decision.note)
Webhook integration examples
Express.js
const express = require('express');
const app = express();
app.post('/webhook', express.json(), async (req, res) => {
const { event, request_id, status, payload, decision_note } = req.body;
console.log(`Received ${event} for ${request_id}: ${status}`);
if (event === 'request.decided') {
try {
if (status === 'approved') {
await handleApproval(payload);
} else {
await handleRejection(payload, decision_note);
}
res.json({ received: true });
} catch (error) {
console.error('Webhook processing error:', error);
res.status(500).json({ error: error.message });
}
} else {
res.json({ received: true, ignored: true });
}
});
async function handleApproval(payload) {
// Process the approved request
await processRefund(payload.customer_id, payload.amount);
await sendCustomerEmail(payload.customer_id, 'approved');
}
async function handleRejection(payload, note) {
// Log rejection
await logRejection(payload, note);
}
app.listen(3000);
FastAPI (Python)
from fastapi import FastAPI, Request
from typing import Dict
app = FastAPI()
@app.post('/webhook')
async def webhook(request: Request):
data: Dict = await request.json()
event = data.get('event')
status = data.get('status')
payload = data.get('payload')
if event == 'request.decided':
if status == 'approved':
await handle_approval(payload)
else:
await handle_rejection(payload, data.get('decision_note'))
return {'received': True}
async def handle_approval(payload):
customer_id = payload['customer_id']
amount = payload['amount']
# Process refund
await process_refund(customer_id, amount)
await send_notification(customer_id, 'refund_approved')
async def handle_rejection(payload, note):
# Log the rejection
await log_rejection(payload, note)
Tips
Add context to payload
Include everything the approver needs to make a decision:
{
"title": "Approve $500 refund for Jane Doe",
"payload": {
"customer_id": "cust_123",
"customer_name": "Jane Doe",
"customer_since": "2023-01-15",
"total_purchases": 2400,
"refund_amount": 500,
"reason": "Product arrived damaged",
"order_id": "ord_456",
"order_date": "2026-01-10",
"support_ticket": "https://support.example.com/tickets/789"
}
}
Use external_id for idempotency
Use your own IDs to prevent duplicate submissions:
external_id = f"refund-{customer_id}-{order_id}"
Set expiration for time-sensitive requests
expires_at = (datetime.now() + timedelta(hours=1)).isoformat()
Use webhooks over polling
Webhooks are instant and don’t waste API calls. Only poll as a fallback.