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.

When an external AI agent talks to a website running Animam, it does not get direct access to the site’s tools. It talks to the Animam chatbot agent, and the chatbot orchestrates the tools (corpus lookup, calendar booking, payment, product recommendations, etc.) on its behalf. This is the only public agent surface. There is no separate tools/list endpoint exposed to anonymous callers — the chatbot is the agent.

Endpoint

POST https://api.animam.ai/chat/{slug}
No authentication required for tenants that have public chat enabled (default for paid plans). The widget-key gate, if configured, still applies.

Declaring you are an agent

Send the X-Agent-Model header so the chatbot knows it’s talking to another agent (not a human). It tags the conversation, switches the tool channel to api, and triggers the structured JSON envelope response automatically.
curl -X POST https://api.animam.ai/chat/acme-corp \
  -H "Content-Type: application/json" \
  -H "X-Agent-Model: claude-opus-4-7" \
  -d '{
    "message": "What are your business hours?",
    "sessionId": "agent-session-abc123"
  }'
Fallback when you cannot set headers: prefix the first message with [AGENT:model-name] — the chatbot strips it out and treats the rest as the question.
{
  "message": "[AGENT:gpt-4o] What are your business hours?",
  "sessionId": "agent-session-abc123"
}

Response shape (agent-aware)

When X-Agent-Model is present and stream is not explicitly set, you get a single JSON response. No SSE parsing.
{
  "message": "We're open Monday to Friday, 9am to 6pm. Anything else I can help with?",
  "sessionId": "agent-session-abc123",
  "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": [{ "id": "...", "title": "Business hours" }] },
      "timestamp": "2026-05-05T14:32:11.420Z"
    }
  ],
  "contactSubmitted": false,
  "llmSource": "managed",
  "llmProvider": "anthropic",
  "llmModel": "claude-haiku-4-5"
}
FieldTypeDescription
messagestringProse reply from the chatbot
sessionIdstringEchoed back. Reuse it on the next call to keep context
conversationIdstringCanonical conversation handle (DB id)
messageCountnumberTotal messages in this conversation
visitorType"agent" | "human"Resolved from X-Agent-Model header / [AGENT:] prefix
agentModelstring | undefinedEcho of what the caller declared (truncated to 100 chars). Declarative — not verified
toolExecutionsarray | []Tools the chatbot invoked while building the reply. Sanitized: no raw inputs
contactSubmittedbooleantrue if a SUBMIT_FORM tool was successfully called
toolResultsobject | undefinedMap of toolName → success for each tool invoked
status"escalated" | undefinedSet when the chatbot escalated to a human
llmSource"managed" | "passthrough" | "stored" | "webhook"Where the LLM key came from
llmProviderstring"anthropic", "openai", "mistral", …
llmModelstring | undefinedThe exact model that generated the reply (e.g. claude-haiku-4-5). Absent for webhook mode
The HTTP response also carries X-AI-Generated: true (AI Act Art. 50 transparency).

Tool executions, not tool calls

toolExecutions[] reports what the chatbot did internally — not actions you can invoke. The chatbot decides which tools to use based on the question. If the chatbot collects a contact via SUBMIT_FORM, books a meeting via BOOK_MEETING, or charges via COLLECT_PAYMENT, the agent caller sees it in toolExecutions[] with structured data. Useful for:
  • attribution (the agent caller wrote the lead, not a random visitor)
  • follow-up logic (e.g., the agent caller polls a CRM after seeing submission.created)
  • debugging (which tool ran, did it succeed, what did it return)
Raw inputs (the parameters the chatbot passed to the tool) are intentionally not in the envelope to avoid leaking PII the chatbot extracted from the conversation.

Multi-turn conversations

Reuse the returned sessionId (or conversationId):
import requests

URL = "https://api.animam.ai/chat/acme-corp"
HEADERS = {"X-Agent-Model": "claude-opus-4-7", "Content-Type": "application/json"}

r1 = requests.post(URL, headers=HEADERS, json={
    "message": "Do you have an enterprise plan?",
    "sessionId": "agent-session-xyz"
})
data = r1.json()

r2 = requests.post(URL, headers=HEADERS, json={
    "message": "Does it include SSO?",
    "sessionId": "agent-session-xyz"
})
The chatbot keeps full context across messages with the same sessionId.

Streaming (opt-in for agents)

Streaming is the default for browsers but opt-in for agents. Set stream: true to receive SSE chunks, ending with a done event that carries the same envelope fields.
curl -N -X POST https://api.animam.ai/chat/acme-corp \
  -H "Content-Type: application/json" \
  -H "X-Agent-Model: claude-opus-4-7" \
  -d '{"message": "Tell me about your product.", "sessionId": "...", "stream": true}'
data: {"text": "We "}
data: {"text": "build "}
data: {"text": "AI infrastructure..."}
data: {"done": true, "sessionId": "...", "conversationId": "...", "visitorType": "agent", "agentModel": "claude-opus-4-7", "toolExecutions": [], "llmSource": "managed", "llmProvider": "anthropic", "llmModel": "claude-haiku-4-5"}

Discovery before talking

Before sending the first message, an agent can introspect the tenant:
curl https://api.animam.ai/discover/{slug}
Returns bot persona, segments, capabilities, public welcome message — useful to decide which segment to target.

Rate limits

WindowPer-IP limit
1 minute20 messages
1 hour200 messages
When exceeded the API returns HTTP 429 with Retry-After.

Errors

HTTPBodyMeaning
400{ "error": "message and sessionId are required" }Missing required field or message > 15000 chars
403{ "error": "Origin not allowed" }Tenant restricts allowed origins
403{ "error": "Invalid or missing widget key" }Tenant requires a widget key
404{ "error": "Tenant not found" }Bad slug
402{ "error": "Plan not activated", "code": "NOT_ACTIVATED" }Tenant on a plan without widget capability
429{ "error": "Conversation limit reached", "code": "LIMIT_REACHED", "nextResetAt": "..." }Monthly conversation cap hit

Integration examples

Python — agent-to-agent

import requests

def ask_animam_agent(slug: str, question: str, session_id: str, my_model: str) -> dict:
    r = requests.post(
        f"https://api.animam.ai/chat/{slug}",
        headers={"X-Agent-Model": my_model, "Content-Type": "application/json"},
        json={"message": question, "sessionId": session_id},
    )
    r.raise_for_status()
    return r.json()  # full envelope

reply = ask_animam_agent("acme-corp", "Pricing for 50 seats?", "sess-1", "claude-opus-4-7")
print(reply["message"])
print("Tools used:", [t["name"] for t in reply.get("toolExecutions", [])])
print("Generated by:", reply.get("llmModel"))

LangChain Tool

from langchain.tools import Tool
import requests

def acme_chatbot(query: str) -> str:
    r = requests.post(
        "https://api.animam.ai/chat/acme-corp",
        headers={"X-Agent-Model": "claude-opus-4-7", "Content-Type": "application/json"},
        json={"message": query, "sessionId": "langchain-session"},
    )
    return r.json()["message"]

acme_tool = Tool(
    name="AcmeCorpAgent",
    description="Talk to Acme Corp's customer-facing AI agent. It can answer product questions, recommend products, book meetings, collect leads.",
    func=acme_chatbot,
)

Next steps

Agent-Ready

Full agent-readiness layers (.well-known files, MCP, JSON-LD)

Discovery

Introspect a tenant before chatting