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.