Skip to content
AnytimeReply

REST endpoints

Send a message

Send a customer message to an agent and get its answer — the same answer the chat bubble would give. Optionally streamed.

POST/api/v1/chat

Send your API key in the Authorization: Bearer af_live_… header. See Authentication.

Body

agent_idstringrequired
The agent's ID (where to find it).
messagestringrequired
The customer's message, 1–4,000 characters.
user_idstring
Your own ID for this person (max 200 characters). Messages with the same user_id continue the same conversation.
conversation_idstring
Continue a specific conversation returned earlier. It must belong to this agent and have been created through the API.
namestring
The customer's name, saved on a new conversation.
emailstring
The customer's email, saved on a new conversation.
verified_emailstring
An email address your server vouches for. The conversation counts as a verified customer, so actions limited to verified customers can run for this email.
streamboolean
true to receive the answer as Server-Sent Events. Default false.

Without conversation_id or user_id, every request starts a new conversation.

Request

curl https://anytimereply.com/api/v1/chat \
  -H "Authorization: Bearer af_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "AGENT_ID",
    "message": "Do you deliver to Sylhet?",
    "user_id": "customer-123",
    "name": "Rafi",
    "email": "[email protected]"
  }'

Response

200 OK
{
  "conversation_id": "8b1d6c2e-…",
  "message_id": "f04a…",
  "text": "Yes! We deliver across Bangladesh, including Sylhet, in 2–4 days. Delivery is ৳120.",
  "sources": [{ "title": "Shipping & delivery", "url": "https://example.com/shipping" }],
  "confidence": 0.82,
  "handoff": false,
  "waiting_for_human": false,
  "ui": null
}

Response fields

conversation_idstring
Keep it (or keep using your user_id) to continue the conversation.
message_idstring | null
The stored reply. null when no reply was written (see below).
textstring
The agent's answer. Plain text with light Markdown (links, bold, lists).
sourcesarray
Up to 3 pages the answer came from (title, url). Empty when Show sources is off.
confidencenumber | null
How well your knowledge matched the question (0–1). null for Q&A, flows and small talk.
handoffboolean
true when this message handed the chat to your team.
waiting_for_humanboolean
true when your team has taken over this conversation. The AI doesn't answer; text is empty.
uiobject | null
Buttons, forms, tap-to-reply choices and widgets to show under the answer: buttons (id, type, label, url), form, replies (strings) and widgets.

When your team takes over

After a handoff the conversation appears in your Helpdesk inbox. Team replies are stored in the conversation, but the API can't push them to you — read them with GET /api/v1/conversations/{id} (messages with role: "human") or listen for the handoff.requested webhook.

If the chat was paused by Guardrails (spam or a blocklist), text is empty and message_id is null.

Streaming

With "stream": true the response is text/event-stream. Each event is one data: line with JSON:

Text
data: {"type":"meta","conversation_id":"8b1d6c2e-…"}

data: {"type":"token","t":"Yes! We "}

data: {"type":"token","t":"deliver across Bangladesh…"}

data: {"type":"done","message_id":"f04a…","text":"Yes! We deliver across Bangladesh…","sources":[…],"handoff":false,"waiting_for_human":false,"ui":null}
EventFields
metaconversation_id — sent first
tokent — the next piece of text
doneThe full answer: message_id, text, sources, handoff, waiting_for_human, ui
errorerror — a readable message; the stream then ends
Read the stream (Node.js 18+)
const res = await fetch("https://anytimereply.com/api/v1/chat", {
  method: "POST",
  headers: { Authorization: "Bearer " + process.env.ANYTIMEREPLY_API_KEY, "Content-Type": "application/json" },
  body: JSON.stringify({ agent_id: "AGENT_ID", message: "Hi!", user_id: "customer-123", stream: true }),
});
const reader = res.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
for (;;) {
  const { done, value } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });
  const events = buffer.split("\n\n");
  buffer = events.pop();
  for (const e of events) {
    if (!e.startsWith("data: ")) continue;
    const msg = JSON.parse(e.slice(6));
    if (msg.type === "token") process.stdout.write(msg.t);
    if (msg.type === "done") console.log("\n", msg.sources);
  }
}

The final text in done can contain more than the streamed tokens (for example links added after an action) — use it as the source of truth.

Notes

  • Conversations from the API appear in Chat logs with the channel API and fire the conversation.created webhook.
  • Each answer uses message credits like the chat bubble.
  • Answers can take a few seconds (longer when actions run); allow up to 120 seconds before timing out.

Errors

StatusError
400conversation_id not found for this agent · validation errors such as message: Required
401Missing or invalid API key
404Agent not found
429Rate limit (120 requests/minute per key)
Was this page helpful?
Still stuck? Contact us