Back to Dashboard

Documentation

Learn how to use Asyntai

API Reference

Build custom integrations with the Asyntai REST API

Get API Key

Paid Plan Required: API access is available on Starter, Standard, and Pro plans. View pricing

Overview

The Asyntai API allows you to integrate AI-powered customer support into any application. Send messages and receive intelligent responses grounded in your website content and knowledge base.

Authentication

All API requests require authentication using your API key. You can get your API key from the API Settings page.

Include your API key in requests using one of these methods:

  • Authorization header (recommended): Authorization: Bearer YOUR_API_KEY
  • X-API-Key header: X-API-Key: YOUR_API_KEY

Keep your API key secret. Anyone with your key can access your account via the API. Never expose it in client-side code.

Base URL

https://asyntai.com/api/v1/

Endpoints

POST /chat/

Send a message and receive an AI-generated response.

Request Body

{
  "message": "What are your business hours?",
  "session_id": "user_123",      // optional
  "website_id": 1                 // optional
}
Parameter Type Required Description
message string Yes The user's message to send to the AI
session_id string No Unique identifier for the conversation. Use the same session_id to maintain conversation history.
website_id integer No Specific website ID. If not provided, uses your primary website.

Response

{
  "success": true,
  "response": "Our business hours are Monday-Friday, 9 AM to 5 PM EST.",
  "session_id": "user_123"
}

Example (cURL)

curl -X POST https://asyntai.com/api/v1/chat/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message": "What are your business hours?", "session_id": "user_123"}'

Example (Python)

import requests

response = requests.post(
    "https://asyntai.com/api/v1/chat/",
    headers={
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json"
    },
    json={
        "message": "What are your business hours?",
        "session_id": "user_123"
    }
)

data = response.json()
print(data["response"])

Example (JavaScript)

const response = await fetch("https://asyntai.com/api/v1/chat/", {
  method: "POST",
  headers: {
    "Authorization": "Bearer YOUR_API_KEY",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    message: "What are your business hours?",
    session_id: "user_123"
  })
});

const data = await response.json();
console.log(data.response);

GET /websites/

List all websites associated with your account.

Response

{
  "success": true,
  "websites": [
    {
      "id": 1,
      "name": "My Website",
      "domain": "example.com",
      "is_primary": true
    }
  ]
}

Example (cURL)

curl https://asyntai.com/api/v1/websites/ \
  -H "Authorization: Bearer YOUR_API_KEY"

POST /websites/

Create a new AI agent. This does the same thing as adding a website in your dashboard: it makes the agent, reads your site, and writes the first draft of the AI instructions.

Use this to set up customers from your own software. You get back the widget ID and the code to put on the website.

Request Body

Field Type Description
domain string Required. The website address, for example example.com
name string Optional. A display name for the agent. Useful when one website has several agents.
crawl boolean Optional, true by default. Set it to false to create the agent without reading the website. Nothing is crawled and no instructions are written.
force boolean Optional, false by default. Set it to true to add a website you already have. The copy is stored with a number after it.

Response

{
  "success": true,
  "website": {
    "id": 42,
    "domain": "example.com",
    "name": "Support agent",
    "widget_id": "asyntai_ab12cd34ef56",
    "is_primary": true,
    "crawl_started": true,
    "instructions_status": "generating",
    "job_id": "8f2c1e90-..."
  },
  "embed_code": "<script>...</script>"
}

Example (cURL)

curl -X POST https://asyntai.com/api/v1/websites/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain": "example.com", "name": "Support agent"}'

Reading a website takes a few minutes, so this call answers straight away. Check when the agent is ready with the next endpoint.

Errors

Code Meaning
403 You have reached the number of websites your plan allows. The answer tells you the limit.
409 Your account already has this website. Send force as true to add it again.

GET /websites/{id}/

Get one website and see whether it is ready. Use this after you create an agent, to wait until the website has been read and the AI instructions are written.

Response

{
  "success": true,
  "website": {
    "id": 42,
    "domain": "example.com",
    "name": "Support agent",
    "widget_id": "asyntai_ab12cd34ef56",
    "is_primary": true,
    "created_at": "2026-08-11T09:12:00+00:00",
    "ready": true,
    "instructions": {
      "status": "completed",
      "has_instructions": true,
      "characters": 3421
    },
    "crawl": {
      "job_id": "8f2c1e90-...",
      "status": "completed",
      "pages_crawled": 47,
      "pages_found": 50,
      "max_pages": 50,
      "completed_at": "2026-08-11T09:15:31+00:00",
      "error": ""
    },
    "knowledge_items": 47
  },
  "embed_code": "<script>...</script>"
}

The ready field is true when nothing is still running. A crawl that failed also counts as ready, because it has finished. Look at the crawl status to see what happened.

Example (cURL)

curl https://asyntai.com/api/v1/websites/42/ \
  -H "Authorization: Bearer YOUR_API_KEY"

GET PATCH /websites/{id}/settings/

Read or change the chat widget settings for one website. These are the same settings you see on the Customize page: colours, the name of the assistant, the first message, lead capture, and everything else.

Reading the settings

A GET request returns every setting with its current value, plus a locked list. Locked shows the settings your plan cannot change, and which plans they need.

{
  "success": true,
  "settings": {
    "ai_support_name": "AI Assistant",
    "widget_color": "#6366f1",
    "initial_message": "Hi, how can I help you?",
    "hide_branding": false,
    "...": "..."
  },
  "locked": {
    "hide_branding": ["pro", "enterprise"],
    "widget_style": ["pro", "enterprise"]
  }
}

Changing the settings

A PATCH request changes only the settings you send. Everything you leave out stays as it is.

curl -X PATCH https://asyntai.com/api/v1/websites/42/settings/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ai_support_name": "Ava", "widget_color": "#0f172a", "use_emoji": true}'
{
  "success": true,
  "updated": ["ai_support_name", "use_emoji", "widget_color"],
  "settings": { "...": "..." },
  "locked": { "...": "..." }
}

Plans

Each setting needs its own plan, the same as in the dashboard. For example, hiding the Asyntai branding needs the Pro plan, and voice input needs Standard.

Plan needed Settings Examples
Any paid plan 25 widget_color, ai_support_name, initial_message
Starter and above 22 profile_picture, conversation_starters_enabled
Standard and above 25 speech_to_text_enabled, image_vision_enabled, escalation_enabled
Pro 6 hide_branding, widget_style

If you send a setting your plan does not allow, the whole request is refused with code 403 and nothing is saved. The same happens if any value is wrong, for example a colour that is not a hex code. Your settings never end up half changed.

GET PUT /websites/{id}/instructions/

Read or replace the AI instructions for one website. These are the rules that tell the assistant who it is, what it may say, and what it must not say. They are the same instructions you edit in the dashboard.

Reading

{
  "success": true,
  "instructions": "You are the support agent for Acme Tools...",
  "characters": 1979,
  "version": 7,
  "mode": "instructions",
  "ask_questions": true,
  "generation_status": "completed",
  "being_edited_by": null
}

Replacing

A PUT request replaces the whole text, the same as saving in the dashboard. There is no append mode. To add a paragraph, read the instructions, add your text, then write it back.

curl -X PUT https://asyntai.com/api/v1/websites/42/instructions/ \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"instructions": "You are the support agent for Acme Tools...", "version": 7}'

Request Body

Field Type Description
instructions string Required. The complete new text. It replaces everything that was there.
version number Optional but recommended. The version you read. If somebody changed the instructions since then, your write is refused instead of overwriting their work.
mode string Optional. Either instructions or general.
ask_questions boolean Optional. Whether the assistant asks a follow-up question at the end of its answers.
force boolean Optional, false by default. Needed only when your new text is less than half the length of the current text.

How your instructions are protected

Instructions can take hours to write, so a write can be refused to protect them:

Code Meaning
400 Your new text is less than half the length of the current text. This catches a script that sends empty or cut-off text over instructions somebody spent hours on. Send force as true if you meant it.
409 The instructions changed after you read them. Read them again, apply your change, then write.
423 Somebody is editing the instructions in the dashboard right now. The answer tells you who. Try again in a couple of minutes.

Every change also saves a copy of the previous text, so an earlier version can always be restored from the dashboard.

GET /conversations/

Retrieve conversation history for a specific session.

Query Parameters

Parameter Type Required Description
session_id string Yes The session ID to retrieve history for
limit integer No Max messages to return (default: 50, max: 100)

Response

{
  "success": true,
  "session_id": "user_123",
  "messages": [
    {
      "role": "user",
      "content": "What are your business hours?",
      "timestamp": "2024-01-15T10:30:00Z"
    },
    {
      "role": "assistant",
      "content": "Our business hours are Monday-Friday, 9 AM to 5 PM EST.",
      "timestamp": "2024-01-15T10:30:01Z",
      "sender_type": "ai",
      "agent_name": null,
      "response_time_ms": 1840.5
    }
  ]
}

A question and its answer are stored on one record, so both carry the same timestamp. Do not subtract one from the other to measure reply speed, because the result is always zero. Use response_time_ms, which is the real time the answer took, in milliseconds.

sender_type is ai when the chatbot answered, and human when one of your agents took over the chat. agent_name holds the display name of that agent.

Example (cURL)

curl "https://asyntai.com/api/v1/conversations/?session_id=user_123&limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"

GET /sessions/

List your recent chat sessions. Use this to discover session IDs, which you can then pass to /conversations/ to retrieve the full message history.

Query Parameters

Parameter Type Required Description
limit integer No Number of recent sessions to return (default: 20, max: 100)
website_id string No Filter sessions by a specific website ID
source string No Filter by session source: widget, api, whatsapp, instagram, messenger, gorgias, freshchat, zapier

Response

{
  "success": true,
  "sessions": [
    {
      "session_id": "session_abc123def",
      "source": "widget",
      "message_count": 5,
      "first_message": "What are your business hours?",
      "first_message_at": "2024-01-15T10:30:00Z",
      "last_message_at": "2024-01-15T10:35:00Z",
      "first_response_time_ms": 1840.5,
      "first_human_response_at": null,
      "started_at": "2024-01-15T10:29:58Z",
      "ended_at": "2024-01-15T10:41:12Z",
      "taken_over_at": null,
      "website_domain": "example.com"
    }
  ]
}

Timestamp fields for reporting

Field Description
started_at When the visitor opened the chat. Available for widget sessions only, because sessions created through the API never open a widget.
first_message_at When the first message of the conversation was stored.
first_response_time_ms How long the first answer took, in milliseconds. Use this for first response time.
first_human_response_at When one of your agents sent the first reply. It is null when the chatbot handled the whole conversation.
taken_over_at When an agent took the chat over from the chatbot.
last_message_at When the last message of the conversation was stored.
ended_at When the visitor left the chat. A chat has no resolved or closed state, because a visitor can always return and ask another question.

All timestamps are in UTC and use the ISO 8601 format. You cannot change the timezone. Convert the values in your own reporting tool.

Example (cURL)

curl "https://asyntai.com/api/v1/sessions/?limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"

GET /leads/

Retrieve collected leads — email addresses and phone numbers submitted by visitors during chat conversations.

Query Parameters

Parameter Type Required Description
limit integer No Number of leads to return (default: 50, max: 100)
website_id string No Filter leads by a specific website ID

Response

{
  "success": true,
  "leads": [
    {
      "session_id": "session_abc123def",
      "email": "[email protected]",
      "phone": "+1234567890",
      "page_url": "https://example.com/pricing",
      "started_at": "2024-01-15T10:30:00Z"
    }
  ]
}
Field Type Description
session_id string The chat session ID. Pass this to /conversations/ to see the full chat history.
email string or null Email address provided by the visitor, or null if not collected
phone string or null Phone number provided by the visitor, or null if not collected
page_url string or null The page URL where the visitor was chatting
started_at string ISO 8601 timestamp of when the chat session started

Example (cURL)

curl "https://asyntai.com/api/v1/leads/?limit=20" \
  -H "Authorization: Bearer YOUR_API_KEY"

Example (Python)

import requests

response = requests.get(
    "https://asyntai.com/api/v1/leads/",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    params={"limit": 20}
)

leads = response.json()["leads"]
for lead in leads:
    print(f"{lead['email'] or ''} | {lead['phone'] or ''}")

GET /account/

Get your account information and usage statistics.

Response

{
  "success": true,
  "account": {
    "email": "[email protected]",
    "plan": "starter",
    "messages_used": 150,
    "messages_limit": 2500
  }
}

Example (cURL)

curl https://asyntai.com/api/v1/account/ \
  -H "Authorization: Bearer YOUR_API_KEY"

Multiple websites? Knowledge base endpoints default to your primary website. If you have multiple websites, pass website_id to target a specific one. You can find your website IDs using GET /websites/.

Daily upload limits: Knowledge base uploads (text, URL, spreadsheet) are subject to a daily character limit based on your plan. This applies to the total content uploaded across all knowledge base endpoints per day.

Plan Characters/day
Starter300,000
Standard1,500,000
Pro6,000,000

GET /knowledge/

List your knowledge base entries. These are the content sources your AI chatbot uses to answer questions.

Query Parameters

Parameter Type Required Description
limit integer No Number of entries to return (default: 50, max: 100)
website_id string No Filter by website ID (defaults to your primary website)

Response

{
  "success": true,
  "entries": [
    {
      "id": "abc-123-def",
      "type": "text",
      "title": "Business Hours",
      "description": "Manual text content (150 words)",
      "created_at": "2024-01-15T10:30:00Z"
    },
    {
      "id": "ghi-456-jkl",
      "type": "url",
      "title": "About Us - Example",
      "description": "Content from https://example.com/about",
      "created_at": "2024-01-14T09:00:00Z"
    }
  ]
}

Example (cURL)

curl "https://asyntai.com/api/v1/knowledge/?limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY"

POST /knowledge/text/

Add custom text content to your knowledge base. The AI will use this to answer visitor questions.

Request Body

{
  "title": "Return Policy",
  "content": "We offer a 30-day return policy on all items. Items must be unused and in original packaging. Refunds are processed within 5-7 business days.",
  "website_id": "123"
}
Parameter Type Required Description
title string Yes A title for this knowledge entry
content string Yes The text content (min 10 characters)
website_id string No Target website (defaults to your primary website)

Response

{
  "success": true,
  "id": "abc-123-def",
  "title": "Return Policy",
  "chunks_created": 1
}

Example (cURL)

curl -X POST "https://asyntai.com/api/v1/knowledge/text/" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "Return Policy", "content": "We offer a 30-day return policy..."}'

POST /knowledge/url/

Add a webpage to your knowledge base. The content will be fetched and extracted automatically.

Request Body

{
  "url": "https://example.com/faq",
  "website_id": "123"
}
Parameter Type Required Description
url string Yes The URL to fetch content from
website_id string No Target website (defaults to your primary website)

Response

{
  "success": true,
  "id": "abc-123-def",
  "title": "FAQ - Example",
  "url": "https://example.com/faq",
  "chunks_created": 5
}

Example (cURL)

curl -X POST "https://asyntai.com/api/v1/knowledge/url/" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/faq"}'

POST /knowledge/spreadsheet/

Upload a CSV or Excel (.xlsx) spreadsheet to your knowledge base. Each row becomes a separate knowledge entry, ideal for product catalogs, FAQ lists, pricing tables, and directories.

Request

Send as multipart/form-data (file upload), not JSON.

Parameter Type Required Description
file file Yes A .csv or .xlsx file. First row must be column headers. Max rows per upload: Starter 500, Standard 2,000, Pro 10,000. Excess rows are truncated.
website_id string No Target website (defaults to your primary website)

Response

{
  "success": true,
  "id": "abc-123-def",
  "title": "products.csv",
  "rows_processed": 15,
  "chunks_created": 15
}

Example (cURL)

curl -X POST "https://asyntai.com/api/v1/knowledge/spreadsheet/" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "[email protected]"

GET /knowledge/{id}/

Read one knowledge base entry, including the text stored for it. The id comes from the GET /knowledge/ response.

Content is returned for the entries you supplied: text, files, spreadsheets, single URLs and videos. A website crawl is listed but its pages are not returned, because the source is your own public website. In that case content is null and a reason field explains why.

Response

{
  "success": true,
  "id": "abc-123-def",
  "type": "text",
  "title": "Business Hours",
  "description": "Manual text content (150 words)",
  "created_at": "2024-01-15T10:30:00Z",
  "chunks_count": 3,
  "content": "We are open Monday to Friday, 9am to 5pm...",
  "content_available": true,
  "char_count": 43
}

Example (cURL)

curl "https://asyntai.com/api/v1/knowledge/abc-123-def/" \
  -H "Authorization: Bearer YOUR_API_KEY"

DELETE /knowledge/{id}/

Delete a knowledge base entry. The id can be found from the GET /knowledge/ response.

Response

{
  "success": true,
  "message": "Knowledge base entry deleted"
}

Example (cURL)

curl -X DELETE "https://asyntai.com/api/v1/knowledge/abc-123-def/" \
  -H "Authorization: Bearer YOUR_API_KEY"

Tip: You can also manage webhooks from the API Settings page without writing any code.

GET /webhooks/

List your registered webhooks.

Response

{
  "success": true,
  "webhooks": [
    {
      "id": "abc-123-def",
      "url": "https://example.com/webhook",
      "events": ["message.received", "escalation.requested"],
      "is_active": true,
      "created_at": "2024-01-15T10:30:00Z"
    }
  ]
}

Example (cURL)

curl "https://asyntai.com/api/v1/webhooks/" \
  -H "Authorization: Bearer YOUR_API_KEY"

POST /webhooks/

Register a new webhook to receive real-time event notifications.

Available Events

Event Description
message.received A visitor sent a message and received a response
conversation.started A new chat session was started
escalation.requested The AI triggered an escalation to a human agent
takeover.started A human agent took over a chat session

Request Body

{
  "url": "https://example.com/webhook",
  "events": ["message.received", "escalation.requested"],
  "website_id": "123"
}
Parameter Type Required Description
url string Yes The HTTPS URL to receive webhook POST requests
events array Yes List of events to subscribe to (see table above)
website_id string No Target website (defaults to your primary website)

Response

{
  "success": true,
  "webhook": {
    "id": "abc-123-def",
    "url": "https://example.com/webhook",
    "events": ["message.received", "escalation.requested"],
    "secret": "whsec_abc123...",
    "created_at": "2024-01-15T10:30:00Z"
  }
}

Verifying webhooks: Each webhook includes a secret (shown only on creation). Every POST to your URL includes an X-Webhook-Signature header — an HMAC-SHA256 of the request body signed with your secret.

Example (cURL)

curl -X POST "https://asyntai.com/api/v1/webhooks/" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/webhook", "events": ["message.received"]}'

DELETE /webhooks/{id}/

Delete a webhook. The id can be found from the GET /webhooks/ response.

Response

{
  "success": true,
  "message": "Webhook deleted"
}

Example (cURL)

curl -X DELETE "https://asyntai.com/api/v1/webhooks/abc-123-def/" \
  -H "Authorization: Bearer YOUR_API_KEY"

Error Responses

All error responses follow this format:

{
  "success": false,
  "error": "Error message describing what went wrong"
}
Status Code Description
400 Bad Request - Invalid parameters or missing required fields
401 Unauthorized - Invalid or missing API key
429 Too Many Requests - Message limit reached for your plan
503 Service Unavailable - AI service temporarily unavailable

Rate Limits

API usage is limited by your subscription plan:

  • Free: 100 messages/month
  • Starter ($39/mo): 2,500 messages/month
  • Standard ($139/mo): 15,000 messages/month
  • Pro ($449/mo): 50,000 messages/month

Need Help?

If you have any questions or run into issues, contact us at [email protected].