Errors

Every API error code referenced below.

Error response shape

Non-2xx responses are JSON.

{
  "error": "Human-readable message"
}

Status codes

HTTPTypical errorCauseRemedyRetryable
400Bad RequestRequest body failed validation.Fix the payload. Check endpoint reference.No
401UnauthorizedAPI key missing, malformed, or revoked.Send Authorization: Bearer hm_live_...No
403ForbiddenValid credentials, insufficient permission or plan.Upgrade plan or check agent access.No
404Not FoundAgent or resource does not exist.Verify the agent ID and endpoint URL.No
413Payload Too LargeMessage over 4,000 characters.Shorten the message body.No
429Rate limit exceededQuota or rate limit hit.Back off and retry after Retry-After.Yes, with backoff
500Internal Server ErrorUnhandled server-side failure.Retry with exponential backoff.Yes, with backoff
502Bad GatewayUpstream model call failed.Retry with backoff.Yes, with backoff
503Service UnavailableService temporarily overloaded.Retry with backoff.Yes, with backoff

Retry guidance

Treat the Retryable column as authoritative.

import time
import random
import requests

RETRYABLE = {429, 500, 502, 503}

def request_with_retry(method, url, headers=None, json=None, max_attempts=5):
    for attempt in range(max_attempts):
        resp = requests.request(method, url, headers=headers, json=json)
        if resp.status_code < 400 or resp.status_code not in RETRYABLE:
            return resp
        retry_after = resp.headers.get("Retry-After")
        delay = float(retry_after) if retry_after else min(2 ** attempt, 30) + random.random()
        time.sleep(delay)
    return resp

Rate limits

Limits apply to chat and handoff-ticket requests, checked independently.

ScopeDefault limitWindow
Per IP30 requests60s
Per session20 requests60s
Per agent120 requests60s