Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.animam.ai/llms.txt

Use this file to discover all available pages before exploring further.

The public chat endpoint is the only public agent surface on Animam. Browsers (via the widget) and external AI agents both go through it. The chatbot owns all tools — EXPLORE_CORPUS, RECOMMEND_PRODUCT, SUBMIT_FORM, BOOK_MEETING, COLLECT_PAYMENT, etc. — and orchestrates them on the caller’s behalf. There is no separate tools/list endpoint exposed to anonymous callers.

POST /chat/

POST https://api.animam.ai/chat/{slug}
Auth: none required. Origin/widget-key gates apply if the tenant has them configured. Plan must include the widget capability.

Request body

FieldTypeRequiredDescription
messagestring (≤ 15000)YesThe user (or agent) message
sessionIdstring (≤ 100)YesSession handle. Reuse to keep multi-turn context
segmentstringNoSegment slug, defaults to the tenant’s default segment
streambooleanNotrue → SSE. Defaults: true for human visitors, false when X-Agent-Model is present
pageUrlstringNoOptional page URL where the conversation happens
pageContextobjectNo{ title, url, ... } — optional page metadata
visitorIdstringNoPersistent visitor handle (alternative to X-Visitor-Id header)
visitorTokenstringNoJWT signed by tenant’s visitorSigningKey (Mode A auth)
turnstileTokenstringNoRequired if the tenant has Turnstile enabled
localestring (en, fr)NoLocale hint (alternative to X-Animam-Locale header)

Headers

HeaderPurpose
X-Agent-ModelDeclare the calling agent’s model (e.g. claude-opus-4-7). Triggers the agent envelope
X-API-Key / X-LLM-KeyOptional BYOK passthrough — call the tenant’s chatbot with your own LLM key
X-LLM-Provider, X-LLM-Model, X-LLM-Base-UrlBYOK provider config
X-Visitor-Token, X-Visitor-IdVisitor identity propagation
X-Animam-Admin-Token(WordPress) admin JWT for capability-scoped MCP tool access
X-Animam-LocaleLocale hint (en, fr, …)

Response — JSON envelope (default for agents)

When X-Agent-Model is present and stream is not explicitly set, the API returns a single JSON document.
{
  "message": "We're open Monday to Friday, 9am to 6pm.",
  "sessionId": "agent-session-abc",
  "conversationId": "d67e62ae-7b5c-405f-9bec-f1352d3de988",
  "messageCount": 2,
  "visitorType": "agent",
  "agentModel": "claude-opus-4-7",
  "toolExecutions": [
    {
      "name": "explore_corpus",
      "type": "EXPLORE_CORPUS",
      "success": true,
      "summary": "Found 1 entry: business-hours",
      "data": { "entries": [...] },
      "timestamp": "2026-05-05T14:32:11.420Z"
    }
  ],
  "contactSubmitted": false,
  "toolResults": { "explore_corpus": true },
  "llmSource": "managed",
  "llmProvider": "anthropic",
  "llmModel": "claude-haiku-4-5"
}
FieldDescription
messageProse reply from the chatbot
conversationIdDB conversation handle
visitorType"agent" if X-Agent-Model or [AGENT:] prefix detected, else "human"
agentModelDeclarative echo of what the caller said. Truncated to 100 chars. Not cryptographically verified
toolExecutionsTools the chatbot invoked — sanitized: name, type, success flag, one-line summary, structured data, timestamp. Raw inputs intentionally omitted (PII risk)
contactSubmittedtrue if a SUBMIT_FORM tool succeeded — useful for lead attribution
llmModelExact model that generated the reply (e.g. claude-haiku-4-5). Absent when llmSource: "webhook"
status"escalated" when the chatbot triggered ESCALATE_TO_HUMAN
The HTTP response also carries X-AI-Generated: true (AI Act Art. 50 transparency).

Response — SSE stream (default for browsers)

When stream: true (the default for human visitors), the API returns Server-Sent Events.
data: {"text": "We're "}
data: {"text": "open "}
data: {"text": "Monday to Friday..."}
data: {"done": true, "sessionId": "...", "conversationId": "...", "messageCount": 2, "visitorType": "human", "llmSource": "managed", "llmProvider": "anthropic", "llmModel": "claude-haiku-4-5"}
The terminal done event carries all the envelope fields shown in the JSON shape (including toolExecutions when the caller is an agent).

Errors

HTTPCodeBody
400{"error": "message and sessionId are required"}
400{"error": "Message too long (max 15000 chars)"}
403{"error": "Origin not allowed"}
403{"error": "Invalid or missing widget key"}
403TURNSTILE_REQUIRED / TURNSTILE_FAILEDTurnstile gate
402NOT_ACTIVATEDPlan does not include widget capability
404{"error": "Tenant not found"}
429LIMIT_REACHED{"error": "...", "current", "limit", "nextResetAt"}

Rate limits

Per-IP dual window: 20 messages / minute + 200 messages / hour. Exceeded calls return HTTP 429.

Quick examples

Agent-to-agent (Python)

import requests

r = requests.post(
    "https://api.animam.ai/chat/acme-corp",
    headers={"X-Agent-Model": "claude-opus-4-7", "Content-Type": "application/json"},
    json={"message": "What plans do you offer?", "sessionId": "sess-1"},
)
envelope = r.json()
print(envelope["message"])
print("Generated by:", envelope.get("llmModel"))

Streaming (JavaScript widget)

const res = await fetch(`https://api.animam.ai/chat/${slug}`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ message: userInput, sessionId, stream: true })
})
const reader = res.body.getReader()
const decoder = new TextDecoder()
while (true) {
  const { done, value } = await reader.read()
  if (done) break
  for (const line of decoder.decode(value).split('\n')) {
    if (line.startsWith('data: ')) {
      const evt = JSON.parse(line.slice(6))
      if (evt.text) appendToChat(evt.text)
      if (evt.done) finalize(evt)
    }
  }
}

See also

Agent access guide

Full agent-to-agent walkthrough

Tools (concept)

The 13 tool types the chatbot can invoke