EduChat API Documentation
v1.0.0The EduChat REST API gives you programmatic access to your leads, conversations, analytics, and webhook management. Build custom integrations, sync data to your CRM, or create internal dashboards.
Base URL: https://app.educhat.de/api/v1
Authentication
All API v1 endpoints require a Bearer token in the Authorization header. API keys use the ec_ prefix and are available exclusively on the SCALE plan.
Authorization: Bearer ec_test_xxxxxxxxxxxx- Ensure your tenant is on the SCALE plan.
- Navigate to Settings > API Keys in the EduChat dashboard.
- Click "Create API Key" and give it a descriptive name.
- Copy the key immediately and store it in a secure location.
Rate Limits
Rate limits are enforced per API key using a sliding window of 60 seconds. When exceeded, the API returns 429 Too Many Requests with a Retry-After header.
| Plan | Requests / minute | API Access |
|---|---|---|
| STARTER | 30 | Not available |
| GROWTH | 60 | Not available |
| SCALE | 120 | Full access |
Every response includes rate limit information:
| Header | Description |
|---|---|
X-RateLimit-Limit | Max requests allowed in the window |
X-RateLimit-Remaining | Remaining requests in the current window |
X-RateLimit-Reset | Seconds until the window resets |
Retry-After | Seconds to wait before retrying (only on 429) |
Pagination
List endpoints use cursor-free page-based pagination. Pass page and limit as query parameters. The response includes a pagination object.
{
"data": [...],
"pagination": {
"page": 1,
"limit": 20,
"total": 42,
"totalPages": 3
}
}| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number (1-based) |
limit | integer | 20 | Items per page (1-100) |
Leads
Access leads captured by the chatbot. Leads are scored 0-100 and categorized into tiers: COLD (<50), WARM (50-79), HOT (80+).
GET/api/v1/leadsList leads
Returns a paginated list of leads captured by the chatbot, ordered by creation date (newest first).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page | query | integer | No | Page number(default: 1) |
limit | query | integer | No | Items per page (max 100)(default: 20) |
Example Request
curl -X GET "https://app.educhat.de/api/v1/leads?page=1&limit=20" \
-H "Authorization: Bearer ec_test_xxxxxxxxxxxx"Example Response 200 OK
{
"data": [
{
"id": "clx1abc2d0001ab12example",
"name": "Max Mustermann",
"phoneNumber": "+4915112345678",
"email": "max@example.de",
"courseInterest": "Weiterbildung IT",
"score": 85,
"tier": "HOT",
"createdAt": "2026-02-28T14:30:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 42,
"totalPages": 3
}
}Conversations
Access chatbot conversations across all channels (WEB, WHATSAPP, EMBED).
GET/api/v1/conversationsList conversations
Returns a paginated list of conversations, ordered by creation date (newest first). Each entry includes a message count.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page | query | integer | No | Page number(default: 1) |
limit | query | integer | No | Items per page (max 100)(default: 20) |
Example Request
curl -X GET "https://app.educhat.de/api/v1/conversations?page=1&limit=20" \
-H "Authorization: Bearer ec_test_xxxxxxxxxxxx"Example Response 200 OK
{
"data": [
{
"id": "clx1abc2d0002ab12example",
"channel": "WHATSAPP",
"status": "ACTIVE",
"messageCount": 12,
"createdAt": "2026-02-28T14:00:00.000Z",
"updatedAt": "2026-02-28T14:30:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 156,
"totalPages": 8
}
}Bot Configuration
Retrieve your chatbot's current personality, greeting text, and configuration.
GET/api/v1/bot-configGet bot configuration
Returns the current bot configuration including name, institution, greeting, tone, and persona.
Example Request
curl -X GET "https://app.educhat.de/api/v1/bot-config" \
-H "Authorization: Bearer ec_test_xxxxxxxxxxxx"Example Response 200 OK
{
"data": {
"id": "clx1abc2d0003ab12example",
"botName": "StudyBot",
"institutionName": "Bildungszentrum Musterstadt",
"greetingText": "Hallo! Ich bin StudyBot, der KI-Assistent des Bildungszentrums Musterstadt.",
"tone": "professional",
"persona": "friendly_expert",
"createdAt": "2026-01-15T10:00:00.000Z",
"updatedAt": "2026-02-20T16:45:00.000Z"
}
}Tenant Readiness
The readiness score (0-100) indicates how prepared your tenant is to go live. It is calculated from 5 weighted dimensions and is capped at 70 until you receive your first HOT lead.
GET/api/v1/tenant/readinessGet readiness score
Returns the tenant's go-live readiness score with a breakdown of all 5 dimensions: bot configured (25%), knowledge base (20%), HubSpot connected (25%), first conversation (15%), and first HOT lead (15%).
Example Request
curl -X GET "https://app.educhat.de/api/v1/tenant/readiness" \
-H "Authorization: Bearer ec_test_xxxxxxxxxxxx"Example Response 200 OK
{
"data": {
"score": 70,
"cappedAt70": true,
"dimensions": {
"botConfigured": {
"label": "Bot konfiguriert",
"description": "System-Prompt und Bot-Persönlichkeit eingerichtet",
"weight": 25,
"met": true,
"actionPath": "/bot-einrichten"
},
"knowledgeBase": {
"label": "Wissensdatenbank",
"weight": 20,
"met": true
},
"hubspotConnected": {
"label": "HubSpot verbunden",
"weight": 25,
"met": true
},
"firstConversation": {
"label": "Erstes Gespräch",
"weight": 15,
"met": true
},
"firstHotLead": {
"label": "Erster HOT-Lead",
"weight": 15,
"met": false
}
}
}
}Analytics
Access aggregate analytics and the conversion funnel. Use the period parameter to specify the time window: 7d, 30d, or 90d.
GET/api/v1/analytics/overviewGet analytics overview
Returns aggregate analytics for the specified time period: total conversations, total leads, HOT leads, and average messages per conversation.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
period | query | string | No | Time period: 7d, 30d, or 90d(default: 30d) |
Example Request
curl -X GET "https://app.educhat.de/api/v1/analytics/overview?period=30d" \
-H "Authorization: Bearer ec_test_xxxxxxxxxxxx"Example Response 200 OK
{
"data": {
"totalConversations": 156,
"totalLeads": 42,
"hotLeads": 8,
"avgMessagesPerConversation": 7.3
},
"period": "30d"
}GET/api/v1/analytics/funnelGet conversion funnel
Returns the conversion funnel: conversations -> leads -> HOT leads -> handoffs, with counts and conversion rates for each stage.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
period | query | string | No | Time period: 7d, 30d, or 90d(default: 30d) |
Example Request
curl -X GET "https://app.educhat.de/api/v1/analytics/funnel?period=30d" \
-H "Authorization: Bearer ec_test_xxxxxxxxxxxx"Example Response 200 OK
{
"data": {
"stages": [
{ "name": "conversations", "count": 156, "conversionRate": 100 },
{ "name": "leads", "count": 42, "conversionRate": 26.92 },
{ "name": "hotLeads", "count": 8, "conversionRate": 19.05 },
{ "name": "handoffs", "count": 3, "conversionRate": 37.5 }
]
},
"period": "30d"
}API Key Management
GET/api/v1/keysList API keys (masked)
Returns all API keys for the tenant. Keys are masked — only the last 8 characters are visible. Requires ADMIN or OWNER role.
Example Request
curl -X GET "https://app.educhat.de/api/v1/keys" \
-H "Cookie: sb-access-token=your_session_token"Example Response 200 OK
{
"data": [
{
"id": "clx1abc2d0010ab12example",
"name": "Production Key",
"key": "ec_************************a1b2c3d4",
"lastUsed": "2026-02-28T14:30:00.000Z",
"isActive": true,
"createdAt": "2026-01-15T10:00:00.000Z"
}
]
}POST/api/v1/keysCreate an API key
Creates a new API key with the given name. The full key is only returned once — store it securely. Requires SCALE plan and ADMIN/OWNER role.
Request Body
{
"name": "Production Integration"
}Example Request
curl -X POST "https://app.educhat.de/api/v1/keys" \
-H "Cookie: sb-access-token=your_session_token" \
-H "Content-Type: application/json" \
-d '{"name": "Production Integration"}'Example Response 201 Created 200 OK
{
"data": {
"id": "clx1abc2d0010ab12example",
"name": "Production Integration",
"key": "ec_test_xxxxxxxxxxxx...",
"createdAt": "2026-02-28T14:30:00.000Z"
}
}DELETE/api/v1/keys?id={keyId}Deactivate an API key
Soft-deletes (deactivates) an API key. The key can no longer be used for authentication. Requires ADMIN/OWNER role.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | query | string | Yes | The ID of the API key to deactivate |
Example Request
curl -X DELETE "https://app.educhat.de/api/v1/keys?id=clx1abc2d0010ab12example" \
-H "Cookie: sb-access-token=your_session_token"Example Response 200 OK
{
"success": true
}Webhooks
Configure webhook endpoints to receive real-time notifications when events occur in your EduChat tenant. Webhooks are delivered as HTTP POST requests with HMAC-SHA256 signatures.
GET/api/v1/webhooksList webhook endpoints
Returns a paginated list of active webhook endpoints for the tenant.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page | query | integer | No | Page number(default: 1) |
limit | query | integer | No | Items per page (max 100)(default: 20) |
Example Request
curl -X GET "https://app.educhat.de/api/v1/webhooks" \
-H "Authorization: Bearer ec_test_xxxxxxxxxxxx"Example Response 200 OK
{
"data": [
{
"id": "clx1abc2d0020ab12example",
"name": "CRM Integration",
"url": "https://example.de/webhooks/educhat",
"events": ["lead.created", "lead.tier_changed"],
"isActive": true,
"createdAt": "2026-02-15T10:00:00.000Z",
"updatedAt": "2026-02-15T10:00:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 2,
"totalPages": 1
}
}POST/api/v1/webhooksCreate a webhook endpoint
Creates a new webhook endpoint. A signing secret is generated and returned in the response — store it securely for signature verification. The secret is only visible once.
Request Body
{
"url": "https://example.de/webhooks/educhat",
"events": ["lead.created", "lead.tier_changed"],
"name": "CRM Integration"
}Example Request
curl -X POST "https://app.educhat.de/api/v1/webhooks" \
-H "Authorization: Bearer ec_test_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.de/webhooks/educhat",
"events": ["lead.created", "lead.tier_changed"],
"name": "CRM Integration"
}'Example Response 201 Created 200 OK
{
"data": {
"id": "clx1abc2d0020ab12example",
"name": "CRM Integration",
"url": "https://example.de/webhooks/educhat",
"events": ["lead.created", "lead.tier_changed"],
"secret": "whsec_test_xxxxxxxxxxxx...",
"isActive": true,
"createdAt": "2026-02-28T14:30:00.000Z"
}
}GET/api/v1/webhooks/{id}Get a webhook endpoint
Returns a single webhook endpoint by ID.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Webhook endpoint ID |
Example Request
curl -X GET "https://app.educhat.de/api/v1/webhooks/clx1abc2d0020ab12example" \
-H "Authorization: Bearer ec_test_xxxxxxxxxxxx"Example Response 200 OK
{
"data": {
"id": "clx1abc2d0020ab12example",
"name": "CRM Integration",
"url": "https://example.de/webhooks/educhat",
"events": ["lead.created", "lead.tier_changed"],
"isActive": true,
"createdAt": "2026-02-15T10:00:00.000Z",
"updatedAt": "2026-02-15T10:00:00.000Z"
}
}DELETE/api/v1/webhooks/{id}Delete a webhook endpoint
Soft-deletes a webhook endpoint (sets isActive to false). It will no longer receive events.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Webhook endpoint ID |
Example Request
curl -X DELETE "https://app.educhat.de/api/v1/webhooks/clx1abc2d0020ab12example" \
-H "Authorization: Bearer ec_test_xxxxxxxxxxxx"Example Response 200 OK
{
"success": true
}GET/api/v1/webhooks/{id}/deliveriesList webhook deliveries
Returns a paginated list of delivery attempts for a specific webhook endpoint, ordered by date (newest first). Useful for debugging failed deliveries.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Webhook endpoint ID |
page | query | integer | No | Page number(default: 1) |
limit | query | integer | No | Items per page (max 100)(default: 20) |
Example Request
curl -X GET "https://app.educhat.de/api/v1/webhooks/clx1abc2d0020ab12example/deliveries" \
-H "Authorization: Bearer ec_test_xxxxxxxxxxxx"Example Response 200 OK
{
"data": [
{
"id": "clx1abc2d0030ab12example",
"event": "lead.created",
"statusCode": 200,
"response": "{\"ok\":true}",
"success": true,
"attempts": 1,
"createdAt": "2026-02-28T14:30:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 15,
"totalPages": 1
}
}POST/api/v1/webhooks/{id}/testSend a test ping
Sends a test.ping event to the specified webhook endpoint and returns the result synchronously. Use this to verify your endpoint is correctly configured.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id | path | string | Yes | Webhook endpoint ID |
Example Request
curl -X POST "https://app.educhat.de/api/v1/webhooks/clx1abc2d0020ab12example/test" \
-H "Authorization: Bearer ec_test_xxxxxxxxxxxx"Example Response 200 OK
{
"data": {
"success": true,
"statusCode": 200,
"response": "{\"ok\":true}"
}
}Webhook Events & Payloads
Webhooks are delivered as HTTP POST requests with the following envelope format:
{
"event": "lead.created",
"timestamp": "2026-02-28T14:30:00.000Z",
"tenant_id": "clx1abc...",
"data": { ... }
}| Event | Description | Data Fields |
|---|---|---|
lead.created | A new lead was captured | id, name, email, phoneNumber, courseInterest, score, tier |
lead.updated | An existing lead was updated | id, name, email, phoneNumber, courseInterest, score, tier |
lead.tier_changed | A lead's tier changed (e.g. WARM to HOT) | id, previousTier, newTier, score |
conversation.completed | A conversation was completed | id, channel, messageCount, leadId |
handoff.requested | A sales handoff was triggered | conversationId, leadId, reason, assignedToUserId |
Every webhook delivery includes an X-EduChat-Signature header containing an HMAC-SHA256 signature of the request body, signed with your endpoint's secret. Always verify the signature before processing.
The X-EduChat-Event header contains the event type for routing convenience.
// Node.js signature verification example
const crypto = require("crypto");
function verifyWebhookSignature(body, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(body)
.digest("hex");
const received = signature.replace("sha256=", "");
return crypto.timingSafeEqual(
Buffer.from(expected, "hex"),
Buffer.from(received, "hex")
);
}
// In your webhook handler:
app.post("/webhooks/educhat", (req, res) => {
const signature = req.headers["x-educhat-signature"];
const event = req.headers["x-educhat-event"];
const rawBody = JSON.stringify(req.body);
if (!verifyWebhookSignature(rawBody, signature, WEBHOOK_SECRET)) {
return res.status(401).json({ error: "Invalid signature" });
}
// Process the event
const { event: eventType, data } = req.body;
console.log(`Received ${eventType}:`, data);
res.status(200).json({ ok: true });
});- Timeout: 10 seconds — your endpoint must respond within this window.
- Expected response: 2xx status code to confirm receipt.
- Failed deliveries are logged and visible via the
deliveriesendpoint. - Use the
testendpoint to verify your setup before going live.
Error Reference
All error responses follow a consistent format:
{
"error": "Human-readable error message",
"details": [...] // Optional: Zod validation issues
}| Status | Meaning | Common Causes |
|---|---|---|
400 | Bad Request | Invalid query parameters, malformed request body, missing required fields. Check the details array for specific validation errors. |
401 | Unauthorized | Missing Authorization header, invalid API key, deactivated key, or key belongs to a non-SCALE tenant. |
403 | Forbidden | Insufficient role permissions (e.g. MEMBER trying to manage API keys, which requires ADMIN or OWNER). |
404 | Not Found | Requested resource does not exist or does not belong to your tenant. |
429 | Too Many Requests | Rate limit exceeded. Check the Retry-After header for the wait time in seconds. |
500 | Internal Server Error | Unexpected server error. These are logged automatically. If persistent, contact support. |