EnterChat
{ }API reference

API reference

A REST API over the same data the interface uses: conversations, the knowledge base, everything the assistant has been taught, and the work it produced. JSON in, JSON out.

This deployment runs in demo mode. Every endpoint below is live and returns real JSON against a fixed sample dataset — copy any command and run it. Write methods validate your request and return 202 Accepted without persisting anything. Responses carry a "demo": true flag and an X-EnterChat-Mode: demo header.

Base URL

https://api.enterchat.io/v1

Rate limit

600 req / min

Format

JSON · UTF-8

Demo workspaces

This deployment carries five sample businesses instead of one, each with its own conversations, knowledge base, lessons and autonomy settings. In production the workspace is determined by your API key; here you select it with a business query parameter. Omit it and you get the default workspace.

salonStudio LuciaHair salon · Zagrebloc_8f21c
marketMarket KlasGrocery shop · Zagrebloc_3d92a
autopartsAuto Dijelovi DeltaCar parts · Rijekaloc_6b41f
restaurantKonoba FjakaRestaurant · Splitloc_9c78d
gymFit Centar PulsGym · Zagrebloc_2a55e
curl "https://api.enterchat.io/v1/conversations?business=restaurant&status=needs_human" \
  -H "X-API-Key: ech_live_your_key_here"

Conversation ids are unique across workspaces, so /conversations/{id} resolves without the parameter. An unrecognised business value returns 422 rather than falling back to the default.

Authentication

Server-to-server calls use an API key. Keys are created in Settings, shown once, and scoped to a single workspace.

X-API-Key: ech_live_your_key_here

Browser sessions

Authorization: Bearer <session_token>

List endpoints return a paginated envelope. Pass page and per_page; per_page is capped at 100.

GET https://api.enterchat.io/v1/conversations?page=2&per_page=25

{
  "data": [ ... ],
  "meta": {
    "current_page": 2,
    "per_page": 25,
    "total": 8412,
    "last_page": 337
  }
}

Errors

400bad_requestMalformed body or query string.
401unauthenticatedMissing or invalid API key.
403forbiddenKey is not scoped to this workspace.
404not_foundNo resource matches that identifier.
422unprocessableValidation failed; see error.fields.
429rate_limitedRetry after the seconds given in Retry-After.
{
  "error": {
    "code": "unknown_business",
    "message": "No demo workspace with id bakery.",
    "fields": {
      "business": ["Must be one of: salon, market, autoparts, restaurant, gym"]
    }
  }
}

Inbound webhook

This is the entry point the whole product hangs off. Meta posts here on every customer message; the assistant classifies it, answers from the knowledge base, and either sends or holds a draft according to the autonomy state of that intent.
POST/webhooks/whatsapp

Receives inbound messages in Meta's own envelope. Validates the envelope and acknowledges — which is what a production handler does before queueing, since Meta only needs a 200.

Example request

curl -X POST "https://api.enterchat.io/v1/webhooks/whatsapp" \
  -H "Content-Type: application/json" \
  -d '{
    "object": "whatsapp_business_account",
    "entry": [{
      "id": "1029384756102938",
      "changes": [{
        "field": "messages",
        "value": {
          "messaging_product": "whatsapp",
          "messages": [{
            "from": "385914820117",
            "id": "wamid.HBgLMzg1OTE0ODIwMTE3",
            "timestamp": "1786139640",
            "text": { "body": "Imate li slobodno u subotu?" }
          }]
        }
      }]
    }]
  }'

Example response

{
  "accepted": true,
  "applied": false,
  "message": "1 inbound message(s) was accepted but not persisted — this deployment runs in demo mode.",
  "demo": true
}
GET/webhooks/whatsapp

Meta's subscription handshake. Real, because a webhook that cannot complete a verification challenge is not a webhook.

Query parameters

hub.modestringsubscribe
hub.verify_tokenstringYour configured token
hub.challengestringEchoed back verbatim

Example request

curl "https://api.enterchat.io/v1/webhooks/whatsapp?hub.mode=subscribe&hub.verify_token=your_token&hub.challenge=1158201444"

Example response

1158201444

Conversations

GET/conversations

Lists conversations, newest first.

Query parameters

businessstringDemo only. salon · market · autoparts · restaurant · gym. Defaults to salon
statusstringresolved_by_bot · booked · awaiting_customer · needs_human · handled_by_human
intentstringbooking · pricing · hours · availability · complaint · …
after_hoursbooleantrue returns only what arrived while closed
pageintegerDefault 1
per_pageintegerDefault 25, max 100

Example request

curl "https://api.enterchat.io/v1/conversations?after_hours=true&per_page=1" \
  -H "X-API-Key: ech_live_your_key_here"

Example response

{
  "data": [
    {
      "id": "conv_sal_01",
      "intent": "booking",
      "status": "booked",
      "afterHours": true,
      "startedAt": "2026-08-06T22:14:00Z",
      "lastMessageAt": "2026-08-06T22:19:00Z",
      "windowExpiresAt": "2026-08-07T22:19:00Z",
      "contact": { "name": "Marina Kovač", "phone": "+385 91 ••• ••42", "returning": false },
      "bookingId": "bkg_sal_01",
      "messages": [ ... ]
    }
  ],
  "meta": { "current_page": 1, "per_page": 1, "total": 3, "last_page": 3 }
}
GET/conversations/{id}

Returns one conversation with every message, including the confidence and sources on each assistant reply.

Example request

curl "https://api.enterchat.io/v1/conversations/conv_sal_01" \
  -H "X-API-Key: ech_live_your_key_here"

Example response

{
  "data": {
    "id": "conv_sal_01",
    "messages": [
      {
        "id": "msg_sal_01_2",
        "author": "bot",
        "confidence": 0.96,
        "heldForReview": false,
        "sources": [
          { "kind": "hours",     "label": { "en": "Opening hours · Saturday 09:00–14:00" } },
          { "kind": "knowledge", "refId": "kb_sal_03", "label": { "en": "Service durations" } }
        ],
        "text": { "en": "Good evening! Cut and colour together takes…", "hr": "…" }
      }
    ]
  },
  "business": "salon"
}

Knowledge

GET/knowledge

Everything the assistant is allowed to say, with where each answer came from — written by hand, imported from a file, or learned from a correction.

Query parameters

businessstringDemo only. salon · market · autoparts · restaurant · gym. Defaults to salon

Example request

curl "https://api.enterchat.io/v1/knowledge?business=salon" \
  -H "X-API-Key: ech_live_your_key_here"

Example response

{
  "data": [
    {
      "id": "kb_sal_02",
      "topic": { "en": "Price list · Colour" },
      "questions": [ { "en": "How much is balayage?" } ],
      "answer": { "en": "Roots €55. Full colour €70. Balayage €95 medium length…" },
      "source": "imported",
      "importedFrom": "src_sal_02",
      "usedCount": 512
    }
  ],
  "meta": { "current_page": 1, "per_page": 25, "total": 12, "last_page": 1 }
}
GET/gaps

Questions customers keep asking that the knowledge base cannot answer, ranked by how often. This is the backlog that makes the assistant better.

Query parameters

businessstringDemo only. salon · market · autoparts · restaurant · gym. Defaults to salon

Example request

curl "https://api.enterchat.io/v1/gaps?business=market" \
  -H "X-API-Key: ech_live_your_key_here"

Example response

{
  "data": [
    {
      "id": "gap_mkt_02",
      "question": { "en": "Is what is on the shelf today in stock?" },
      "askCount": 96,
      "escalations": 58,
      "lastAskedAt": "2026-08-07T09:18:00Z",
      "exampleConversationId": "conv_mkt_03"
    }
  ],
  "meta": { "current_page": 1, "per_page": 25, "total": 5, "last_page": 1 }
}

Training

GET/training/sources

Files the workspace has been taught from — WhatsApp exports, price list PDFs, screenshots. Imports are reversible, so this is also the list of what can be revoked.

Query parameters

businessstringDemo only. salon · market · autoparts · restaurant · gym. Defaults to salon
statusstringqueued · reading · mapping · ready · failed

Example request

curl "https://api.enterchat.io/v1/training/sources?business=salon" \
  -H "X-API-Key: ech_live_your_key_here"

Example response

{
  "data": [
    {
      "id": "src_sal_01",
      "filename": "WhatsApp Chat - Studio Lucia.txt",
      "kind": "whatsapp_export",
      "status": "ready",
      "stats": { "conversations": 1284, "messages": 9418, "topicsFound": 31, "gapsFound": 7 }
    },
    {
      "id": "src_sal_04",
      "filename": "stari-cjenik-2023.docx",
      "kind": "docx",
      "status": "failed",
      "error": { "en": "Prices in this file contradict cjenik-2026.pdf on 9 services…" }
    }
  ],
  "meta": { "current_page": 1, "per_page": 25, "total": 4, "last_page": 1 }
}
GET/training/topics

The topic map an import produced, least confident first. Filter status=proposed to get exactly the decisions still waiting on a person.

Query parameters

businessstringDemo only. salon · market · autoparts · restaurant · gym. Defaults to salon
statusstringproposed · approved · edited · rejected
source_idstringNarrow to one import

Example request

curl "https://api.enterchat.io/v1/training/topics?business=salon&status=proposed" \
  -H "X-API-Key: ech_live_your_key_here"

Example response

{
  "data": [
    {
      "id": "tm_sal_08",
      "topic": { "en": "Hair extensions" },
      "occurrences": 61,
      "phrasings": [ { "en": "do you do extensions" } ],
      "confidence": 0.19,
      "status": "proposed",
      "proposedAnswer": { "en": "No proposed answer — nothing in the imported chats gives a consistent answer…" }
    }
  ],
  "meta": { "current_page": 1, "per_page": 25, "total": 3, "last_page": 1 }
}
GET/lessons

Every correction the workspace has taught, with what the assistant used to answer and what it answers now. Reversible by design — an assistant that changes behaviour with no visible record is one nobody can debug.

Query parameters

businessstringDemo only. salon · market · autoparts · restaurant · gym. Defaults to salon

Example request

curl "https://api.enterchat.io/v1/lessons?business=gym" \
  -H "X-API-Key: ech_live_your_key_here"

Example response

{
  "data": [
    {
      "id": "les_gym_01",
      "origin": "human_takeover",
      "trigger": { "en": "I want to cancel" },
      "wasAnswering": { "en": "Cancellation is done in person at reception…" },
      "nowAnswers": { "en": "Answer it straight and completely on the first message…" },
      "appliedCount": 341,
      "active": true
    }
  ],
  "meta": { "current_page": 1, "per_page": 25, "total": 5, "last_page": 1 }
}
GET/autonomy

How much rope each kind of question has earned. An intent climbs from draft to suggest to auto as its accuracy holds above the threshold, and falls back when corrections spike.

Query parameters

businessstringDemo only. salon · market · autoparts · restaurant · gym. Defaults to salon

Example request

curl "https://api.enterchat.io/v1/autonomy?business=restaurant" \
  -H "X-API-Key: ech_live_your_key_here"

Example response

{
  "data": [
    { "intent": "booking",          "state": "auto",  "accuracy": 0.97, "sampleSize": 2104, "threshold": 0.94 },
    { "intent": "product_question", "state": "draft", "accuracy": 0.93, "sampleSize": 512,  "threshold": 0.94, "pinned": true }
  ],
  "meta": { "current_page": 1, "per_page": 25, "total": 10, "last_page": 1 }
}

Work produced

GET/bookings

Appointments, delivery slots and reservations the conversations turned into.

Query parameters

businessstringDemo only. salon · market · autoparts · restaurant · gym. Defaults to salon

Example request

curl "https://api.enterchat.io/v1/bookings?business=salon" \
  -H "X-API-Key: ech_live_your_key_here"

Example response

{
  "data": [
    {
      "id": "bkg_sal_01",
      "contactName": "Marina Kovač",
      "service": { "en": "Cut and colour" },
      "startsAt": "2026-08-08T08:30:00Z",
      "durationMinutes": 150,
      "status": "confirmed",
      "bookedByBot": true,
      "conversationId": "conv_sal_01"
    }
  ],
  "meta": { "current_page": 1, "per_page": 25, "total": 7, "last_page": 1 }
}
GET/leads

Everything that showed intent and did not end in a booking, with the conversation attached — including the ones lost because nobody had written the answer down.

Query parameters

businessstringDemo only. salon · market · autoparts · restaurant · gym. Defaults to salon

Example request

curl "https://api.enterchat.io/v1/leads?business=autoparts" \
  -H "X-API-Key: ech_live_your_key_here"

Example response

{
  "data": [
    {
      "id": "led_aut_01",
      "contactName": "Alen Kovačević",
      "intent": "pricing",
      "stage": "quoted",
      "valueEur": 1574,
      "conversationId": "conv_aut_07",
      "sentToCrm": true
    }
  ],
  "meta": { "current_page": 1, "per_page": 25, "total": 5, "last_page": 1 }
}

Workspace

GET/overview

The dashboard figures, including the after-hours summary and the 24-hour window economics.

Query parameters

businessstringDemo only. salon · market · autoparts · restaurant · gym. Defaults to salon

Example request

curl "https://api.enterchat.io/v1/overview?business=salon" \
  -H "X-API-Key: ech_live_your_key_here"

Example response

{
  "data": {
    "messagesToday": 47,
    "medianResponseSeconds": 8,
    "deflectionRate": 84,
    "conversionRate": 31,
    "awaitingHuman": 2,
    "afterHours": { "messages": 14, "resolved": 11, "booked": 2, "waiting": 1, "closedHours": 14 },
    "window":     { "resolvedInWindow": 412, "missedWindow": 23, "templateCostEur": 1.84 }
  },
  "business": "salon"
}
GET/locations

Every number the key can see. In demo mode that is all five sample workspaces, each carrying the value to pass as business elsewhere.

Example request

curl "https://api.enterchat.io/v1/locations" \
  -H "X-API-Key: ech_live_your_key_here"

Example response

{
  "data": [
    { "id": "loc_8f21c", "demo_business": "salon", "name": "Studio Lucia", "city": "Zagreb",
      "phoneNumber": "+385 1 4820 117", "wabaId": "waba/1029384756102938" },
    { "id": "loc_9c78d", "demo_business": "restaurant", "name": "Konoba Fjaka", "city": "Split",
      "phoneNumber": "+385 21 486 233", "wabaId": "waba/2049183756402918" }
  ],
  "meta": { "current_page": 1, "per_page": 25, "total": 5, "last_page": 1 }
}
POST/contact

The enquiry form behind the website. Validation is real; nothing is delivered.

Example request

curl -X POST "https://api.enterchat.io/v1/contact" \
  -H "Content-Type: application/json" \
  -d '{"name": "Lucia Marić", "email": "lucia@studiolucia.hr", "business": "Studio Lucia"}'

Example response

{
  "accepted": true,
  "applied": false,
  "message": "Your enquiry was accepted but not persisted — this deployment runs in demo mode.",
  "demo": true
}