API v1 · Enterprise

REST API Documentation

Programmatic access to every call, transcript, recording, and analytic for your AI receptionist. Available on the Enterprise plan ($1,997/mo). All responses are JSON. Base URL:

https://humanaddai.com/api/v1

Authentication

Authenticate every request with your API key in the Authorization header. Get your key from the Dashboard → Integrations tab → Custom API card. You can rotate it at any time; the old key dies instantly.

curl https://humanaddai.com/api/v1/calls \
  -H "Authorization: Bearer hak_your_api_key_here"

Never commit your key to version control. If it's ever exposed, rotate immediately from the dashboard.

Errors

All errors return a JSON body with an error code and a human message.

{ "ok": false, "error": "invalid_api_key", "message": "API key not recognized." }
StatusErrorMeaning
401missing_api_keyNo Authorization header sent
401invalid_api_keyKey doesn't exist or has been rotated
403plan_not_supportedAccount is not on Enterprise
404not_foundResource ID doesn't exist
500fetch_failedUpstream error — retry

Rate limits

60 requests per minute per API key. Exceeding returns 429 Too Many Requests.

GET /api/v1/calls

Returns your most recent calls. Paginated via after timestamp.

Query params

  • limit — integer, 1–200, default 50
  • after — unix ms timestamp; only returns calls that started after this

Example

curl "https://humanaddai.com/api/v1/calls?limit=10" \
  -H "Authorization: Bearer hak_..."

{
  "ok": true,
  "count": 10,
  "calls": [
    {
      "call_id": "call_abc123",
      "direction": "inbound",
      "from_number": "+15551234567",
      "to_number":   "+15559876543",
      "started_at":  "2025-01-15T18:22:04.000Z",
      "duration_seconds": 82,
      "status": "ended",
      "sentiment": "positive",
      "summary": "Caller booked an HVAC maintenance appointment for Thursday.",
      "tags": ["booking"],
      "booked": true
    }
  ]
}

GET /api/v1/calls/:id

Full call details including transcript and a proxied recording URL.

curl https://humanaddai.com/api/v1/calls/call_abc123 \
  -H "Authorization: Bearer hak_..."

{
  "ok": true,
  "call": {
    "call_id": "call_abc123",
    "direction": "inbound",
    "from_number": "+15551234567",
    "to_number":   "+15559876543",
    "started_at":  "2025-01-15T18:22:04.000Z",
    "ended_at":    "2025-01-15T18:23:26.000Z",
    "duration_seconds": 82,
    "status": "ended",
    "disconnection_reason": "user_hangup",
    "sentiment": "positive",
    "summary": "...",
    "transcript": "AI: Hello...",
    "transcript_object": [...],
    "recording_url": "/api/v1/calls/call_abc123/recording"
  }
}

GET /api/v1/calls/:id/recording

Streams the call audio as audio/wav. Proxied so you never see the upstream URL.

GET /api/v1/stats

Aggregate metrics for a rolling period.

Query params

  • days — integer, default 30
{
  "ok": true,
  "period_days": 30,
  "stats": {
    "totalCalls": 426,
    "avgDuration": "1:22",
    "answered": 402,
    "missed": 24,
    "inbound": 410,
    "outbound": 16,
    "sentimentDistribution": { "positive": 380, "neutral": 32, "negative": 14 },
    "busiestDay": "Tuesday",
    "peakHours": "9am - 12pm",
    "topQuestions": [...]
  }
}

POST /api/v1/kb

Update your AI's knowledge base programmatically. Changes are queued for review and pushed within minutes.

curl https://humanaddai.com/api/v1/kb \
  -H "Authorization: Bearer hak_..." \
  -H "Content-Type: application/json" \
  -d '{"text": "Our new hours are 8am-7pm M-F.", "replace": false}'

{ "ok": true, "queued": true }

Set replace: true to wipe the existing KB before adding. Use with caution.

Receiving webhooks (outbound)

Configure a webhook URL in Dashboard → Integrations and we'll POST every call_ended event to your endpoint. See the dashboard for payload shape, or receive this JSON:

{
  "event": "call_ended",
  "call_id": "...",
  "direction": "inbound",
  "from_number": "+15551234567",
  "to_number": "+15559876543",
  "started_at": "2025-01-01T00:00:00Z",
  "duration_seconds": 82,
  "sentiment": "positive",
  "summary": "...",
  "transcript": "...",
  "recording_url": "..."
}

If you set a secret in the dashboard, it's sent as X-Webhook-Secret — verify it before processing.

Questions? Need a custom endpoint?

Contact support →