{"openapi":"3.1.0","info":{"title":"EduChat API","version":"1.0.0","description":"Public REST API for EduChat — AI-powered chatbot platform for German education providers.\n\nAPI access requires the **SCALE** plan and a valid API key. Keys are managed from the EduChat dashboard under Settings > API Keys.\n\nAll endpoints are prefixed with `/api/v1` and return JSON responses. Rate limits are enforced per API key based on the tenant plan.","contact":{"name":"EduChat Support","email":"support@educhat.de","url":"https://educhat.de"}},"servers":[{"url":"https://app.educhat.de","description":"Production"},{"url":"http://localhost:3000","description":"Local Development"}],"security":[{"ApiKeyAuth":[]}],"tags":[{"name":"Leads","description":"Access leads captured by the chatbot"},{"name":"Conversations","description":"Access chatbot conversations"},{"name":"Bot Configuration","description":"Read bot personality and settings"},{"name":"Tenant","description":"Tenant-level information and readiness"},{"name":"Analytics","description":"Analytics overview and conversion funnel"},{"name":"API Keys","description":"Manage API keys (requires dashboard authentication, not API key auth)"},{"name":"Webhooks","description":"Manage webhook endpoints, view deliveries, and test"}],"paths":{"/api/v1/leads":{"get":{"operationId":"listLeads","tags":["Leads"],"summary":"List leads","description":"Returns a paginated list of leads captured by the chatbot, ordered by creation date (newest first).","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/LimitParam"}],"responses":{"200":{"description":"Paginated list of leads","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Lead"}},"pagination":{"$ref":"#/components/schemas/PaginationResponse"}}},"example":{"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}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/conversations":{"get":{"operationId":"listConversations","tags":["Conversations"],"summary":"List conversations","description":"Returns a paginated list of conversations, ordered by creation date (newest first). Each entry includes a message count.","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/LimitParam"}],"responses":{"200":{"description":"Paginated list of conversations","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Conversation"}},"pagination":{"$ref":"#/components/schemas/PaginationResponse"}}},"example":{"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}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/bot-config":{"get":{"operationId":"getBotConfig","tags":["Bot Configuration"],"summary":"Get bot configuration","description":"Returns the current bot configuration including name, greeting, tone, and persona.","responses":{"200":{"description":"Bot configuration","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BotConfig"}}},"example":{"data":{"id":"clx1abc2d0003ab12example","botName":"StudyBot","institutionName":"Bildungszentrum Musterstadt","greetingText":"Hallo! Ich bin StudyBot, der KI-Assistent des Bildungszentrums Musterstadt. Wie kann ich Ihnen helfen?","tone":"professional","persona":"friendly_expert","createdAt":"2026-01-15T10:00:00.000Z","updatedAt":"2026-02-20T16:45:00.000Z"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Bot config not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Bot config not found"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/tenant/readiness":{"get":{"operationId":"getTenantReadiness","tags":["Tenant"],"summary":"Get go-live readiness score","description":"Returns the tenant's go-live readiness score (0-100) based on 5 weighted dimensions: bot configured (25%), knowledge base (20%), HubSpot connected (25%), first conversation (15%), and first HOT lead (15%). The score is capped at 70 until the tenant receives their first HOT lead.","responses":{"200":{"description":"Readiness score with dimension breakdown","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ReadinessScore"}}},"example":{"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","description":"Mindestens ein aktives Dokument hochgeladen","weight":20,"met":true,"actionPath":"/wissensdatenbank"},"hubspotConnected":{"label":"HubSpot verbunden","description":"HubSpot API-Key eingetragen","weight":25,"met":true,"actionPath":"/einstellungen"},"firstConversation":{"label":"Erstes Gespräch","description":"Mindestens ein Gespräch geführt","weight":15,"met":true},"firstHotLead":{"label":"Erster HOT-Lead","description":"Mindestens ein qualifizierter HOT-Lead identifiziert","weight":15,"met":false}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/analytics/overview":{"get":{"operationId":"getAnalyticsOverview","tags":["Analytics"],"summary":"Get analytics overview","description":"Returns aggregate analytics for the specified time period: total conversations, total leads, HOT leads, and average messages per conversation.","parameters":[{"$ref":"#/components/parameters/PeriodParam"}],"responses":{"200":{"description":"Analytics overview data","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AnalyticsOverview"},"period":{"type":"string","example":"30d"}}},"example":{"data":{"totalConversations":156,"totalLeads":42,"hotLeads":8,"avgMessagesPerConversation":7.3},"period":"30d"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/analytics/funnel":{"get":{"operationId":"getAnalyticsFunnel","tags":["Analytics"],"summary":"Get conversion funnel","description":"Returns the conversion funnel stages: conversations -> leads -> HOT leads -> handoffs, with counts and conversion rates.","parameters":[{"$ref":"#/components/parameters/PeriodParam"}],"responses":{"200":{"description":"Conversion funnel data","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"stages":{"type":"array","items":{"$ref":"#/components/schemas/FunnelStage"}}}},"period":{"type":"string","example":"30d"}}},"example":{"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"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/keys":{"get":{"operationId":"listApiKeys","tags":["API Keys"],"summary":"List API keys","description":"Returns all API keys for the tenant. Keys are masked — only the last 8 characters are visible. This endpoint uses session-based authentication (dashboard login), not API key auth.","security":[],"responses":{"200":{"description":"List of API keys (masked)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}}}},"example":{"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"}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Requires ADMIN or OWNER role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Requires ADMIN or OWNER role"}}}},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"createApiKey","tags":["API Keys"],"summary":"Create a new API key","description":"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. Uses session-based authentication (dashboard login).","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"A descriptive name for the key","example":"Production Integration"}}}}}},"responses":{"201":{"description":"API key created. The full key is only visible in this response.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ApiKeyCreated"}}},"example":{"data":{"id":"clx1abc2d0010ab12example","name":"Production Integration","key":"ec_test_xxxxxxxxxxxx","createdAt":"2026-02-28T14:30:00.000Z"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Requires SCALE plan and ADMIN/OWNER role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"API keys require the SCALE plan"}}}},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"deactivateApiKey","tags":["API Keys"],"summary":"Deactivate an API key","description":"Soft-deletes (deactivates) an API key. The key can no longer be used for authentication. Uses session-based authentication (dashboard login).","security":[],"parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string"},"description":"The ID of the API key to deactivate"}],"responses":{"200":{"description":"API key deactivated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true}}},"example":{"success":true}}}},"400":{"description":"Missing id parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing 'id' query parameter"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Requires ADMIN or OWNER role","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Requires ADMIN or OWNER role"}}}},"404":{"description":"API key not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"API key not found"}}}},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/webhooks":{"get":{"operationId":"listWebhooks","tags":["Webhooks"],"summary":"List webhook endpoints","description":"Returns a paginated list of active webhook endpoints for the tenant.","parameters":[{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/LimitParam"}],"responses":{"200":{"description":"Paginated list of webhook endpoints","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}},"pagination":{"$ref":"#/components/schemas/PaginationResponse"}}},"example":{"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}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"post":{"operationId":"createWebhook","tags":["Webhooks"],"summary":"Create a webhook endpoint","description":"Creates a new webhook endpoint that will receive events via HTTP POST. A signing secret is generated and returned — store it securely for signature verification. The secret is only visible in this response.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string","format":"uri","description":"The HTTPS URL to deliver events to","example":"https://example.de/webhooks/educhat"},"events":{"type":"array","items":{"type":"string","enum":["lead.created","lead.updated","lead.tier_changed","conversation.completed","handoff.requested"]},"minItems":1,"description":"Events to subscribe to","example":["lead.created","lead.tier_changed"]},"name":{"type":"string","maxLength":100,"description":"Optional display name","example":"CRM Integration"}}}}}},"responses":{"201":{"description":"Webhook endpoint created. The signing secret is only visible in this response.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookEndpointCreated"}}},"example":{"data":{"id":"clx1abc2d0020ab12example","name":"CRM Integration","url":"https://example.de/webhooks/educhat","events":["lead.created","lead.tier_changed"],"secret":"a3f8c9d1e4b7f2a0c5d8e1f4a7b0c3d6e9f2a5b8c1d4e7f0a3b6c9d2e5f8a1","isActive":true,"createdAt":"2026-02-28T14:30:00.000Z"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/webhooks/{id}":{"get":{"operationId":"getWebhook","tags":["Webhooks"],"summary":"Get a webhook endpoint","description":"Returns a single webhook endpoint by ID.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Webhook endpoint ID"}],"responses":{"200":{"description":"Webhook endpoint details","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Webhook endpoint not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Webhook endpoint not found"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"delete":{"operationId":"deleteWebhook","tags":["Webhooks"],"summary":"Delete a webhook endpoint","description":"Soft-deletes a webhook endpoint (sets isActive to false). It will no longer receive events.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Webhook endpoint ID"}],"responses":{"200":{"description":"Webhook endpoint deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true}}},"example":{"success":true}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Webhook endpoint not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Webhook endpoint not found"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/webhooks/{id}/deliveries":{"get":{"operationId":"listWebhookDeliveries","tags":["Webhooks"],"summary":"List webhook deliveries","description":"Returns a paginated list of delivery attempts for a specific webhook endpoint, ordered by date (newest first).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Webhook endpoint ID"},{"$ref":"#/components/parameters/PageParam"},{"$ref":"#/components/parameters/LimitParam"}],"responses":{"200":{"description":"Paginated list of deliveries","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}},"pagination":{"$ref":"#/components/schemas/PaginationResponse"}}},"example":{"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}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Webhook endpoint not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Webhook endpoint not found"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/api/v1/webhooks/{id}/test":{"post":{"operationId":"testWebhook","tags":["Webhooks"],"summary":"Send a test ping","description":"Sends a test.ping event to the specified webhook endpoint and returns the delivery result synchronously. Use this to verify your endpoint is correctly configured and responding.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Webhook endpoint ID"}],"responses":{"200":{"description":"Test delivery result","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"success":{"type":"boolean"},"statusCode":{"type":"integer","nullable":true},"response":{"type":"string","nullable":true}}}}},"example":{"data":{"success":true,"statusCode":200,"response":"{\"ok\":true}"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"description":"Webhook endpoint not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Webhook endpoint not found"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}},"components":{"securitySchemes":{"ApiKeyAuth":{"type":"http","scheme":"bearer","description":"API key with `ec_` prefix. Obtain from the EduChat dashboard under Settings > API Keys. Pass as `Authorization: Bearer ec_...` header. Requires the SCALE plan."}},"parameters":{"PageParam":{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"Page number (1-based)"},"LimitParam":{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"description":"Number of items per page (max 100)"},"PeriodParam":{"name":"period","in":"query","required":false,"schema":{"type":"string","enum":["7d","30d","90d"],"default":"30d"},"description":"Time period for analytics data"}},"headers":{"X-RateLimit-Limit":{"description":"Maximum number of requests allowed in the current window","schema":{"type":"integer","example":120}},"X-RateLimit-Remaining":{"description":"Remaining requests in the current window","schema":{"type":"integer","example":117}},"X-RateLimit-Reset":{"description":"Seconds until the rate limit window resets","schema":{"type":"integer","example":45}}},"responses":{"BadRequest":{"description":"Invalid request — missing or malformed parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Invalid query parameters","details":[{"code":"too_small","minimum":1,"path":["page"],"message":"Number must be greater than or equal to 1"}]}}}},"Unauthorized":{"description":"Authentication failed — missing, invalid, or inactive API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Missing or invalid Authorization header"}}}},"RateLimited":{"description":"Too many requests — rate limit exceeded","headers":{"Retry-After":{"description":"Seconds to wait before retrying","schema":{"type":"integer","example":30}},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Rate limit exceeded. Bitte versuche es in einer Minute erneut."}}}},"InternalError":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"},"example":{"error":"Internal server error"}}}}},"schemas":{"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"},"details":{"type":"array","description":"Validation error details (Zod issues)","items":{"type":"object"}}}},"PaginationResponse":{"type":"object","properties":{"page":{"type":"integer","description":"Current page number","example":1},"limit":{"type":"integer","description":"Items per page","example":20},"total":{"type":"integer","description":"Total number of items","example":42},"totalPages":{"type":"integer","description":"Total number of pages","example":3}}},"Lead":{"type":"object","properties":{"id":{"type":"string","description":"Unique lead ID"},"name":{"type":"string","nullable":true,"description":"Lead's name (if provided)"},"phoneNumber":{"type":"string","nullable":true,"description":"Phone number in E.164 format"},"email":{"type":"string","nullable":true,"description":"Email address"},"courseInterest":{"type":"string","nullable":true,"description":"Course or program the lead expressed interest in"},"score":{"type":"integer","minimum":0,"maximum":100,"description":"Lead score (0-100)"},"tier":{"type":"string","enum":["COLD","WARM","HOT"],"description":"Lead tier based on score: COLD (<50), WARM (50-79), HOT (80+)"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp"}}},"Conversation":{"type":"object","properties":{"id":{"type":"string","description":"Unique conversation ID"},"channel":{"type":"string","enum":["WEB","WHATSAPP","EMBED"],"description":"Channel the conversation originated from"},"status":{"type":"string","enum":["ACTIVE","COMPLETED","HANDOFF"],"description":"Current conversation status"},"messageCount":{"type":"integer","description":"Total number of messages in the conversation"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp of last update"}}},"BotConfig":{"type":"object","properties":{"id":{"type":"string","description":"Bot config ID"},"botName":{"type":"string","description":"Display name of the chatbot"},"institutionName":{"type":"string","description":"Name of the education institution"},"greetingText":{"type":"string","description":"Initial greeting message sent to users"},"tone":{"type":"string","description":"Tone of voice (e.g. professional, casual, friendly)"},"persona":{"type":"string","description":"Bot persona preset (e.g. friendly_expert, formal_advisor)"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp of last update"}}},"ReadinessScore":{"type":"object","properties":{"score":{"type":"integer","minimum":0,"maximum":100,"description":"Overall readiness score (capped at 70 without HOT lead)"},"cappedAt70":{"type":"boolean","description":"Whether the score is currently capped at 70 due to missing HOT lead"},"dimensions":{"type":"object","description":"Breakdown by dimension","additionalProperties":{"type":"object","properties":{"label":{"type":"string","description":"Human-readable label"},"description":{"type":"string","description":"What this dimension measures"},"weight":{"type":"integer","description":"Weight in the total score (sums to 100)"},"met":{"type":"boolean","description":"Whether this dimension's condition is met"},"actionPath":{"type":"string","description":"Dashboard path to take action (if applicable)"}}}}}},"AnalyticsOverview":{"type":"object","properties":{"totalConversations":{"type":"integer","description":"Total conversations in the period"},"totalLeads":{"type":"integer","description":"Total leads captured in the period"},"hotLeads":{"type":"integer","description":"Number of HOT leads in the period"},"avgMessagesPerConversation":{"type":"number","description":"Average number of messages per conversation (1 decimal)"}}},"FunnelStage":{"type":"object","properties":{"name":{"type":"string","enum":["conversations","leads","hotLeads","handoffs"],"description":"Funnel stage name"},"count":{"type":"integer","description":"Number of items in this stage"},"conversionRate":{"type":"number","description":"Conversion rate from previous stage (percentage, 2 decimals). First stage is always 100."}}},"ApiKey":{"type":"object","properties":{"id":{"type":"string","description":"API key ID"},"name":{"type":"string","description":"Key name"},"key":{"type":"string","description":"Masked key — only last 8 characters visible"},"lastUsed":{"type":"string","format":"date-time","nullable":true,"description":"Last time the key was used"},"isActive":{"type":"boolean","description":"Whether the key is active"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp"}}},"ApiKeyCreated":{"type":"object","properties":{"id":{"type":"string","description":"API key ID"},"name":{"type":"string","description":"Key name"},"key":{"type":"string","description":"Full API key (only shown once at creation time)"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp"}}},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string","description":"Webhook endpoint ID"},"name":{"type":"string","nullable":true,"description":"Display name"},"url":{"type":"string","format":"uri","description":"Target URL"},"events":{"type":"array","items":{"type":"string"},"description":"Subscribed event types"},"isActive":{"type":"boolean","description":"Whether the endpoint is active"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp of last update"}}},"WebhookEndpointCreated":{"type":"object","properties":{"id":{"type":"string","description":"Webhook endpoint ID"},"name":{"type":"string","nullable":true,"description":"Display name"},"url":{"type":"string","format":"uri","description":"Target URL"},"events":{"type":"array","items":{"type":"string"},"description":"Subscribed event types"},"secret":{"type":"string","description":"Signing secret for HMAC-SHA256 verification (only shown once)"},"isActive":{"type":"boolean","description":"Whether the endpoint is active"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp"}}},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"string","description":"Delivery attempt ID"},"event":{"type":"string","description":"Event type that was delivered"},"statusCode":{"type":"integer","nullable":true,"description":"HTTP status code returned by the endpoint (null if request failed)"},"response":{"type":"string","nullable":true,"description":"Response body from the endpoint (truncated to 1024 chars)"},"success":{"type":"boolean","description":"Whether the delivery was successful (2xx status)"},"attempts":{"type":"integer","description":"Number of delivery attempts"},"createdAt":{"type":"string","format":"date-time","description":"ISO 8601 timestamp"}}},"WebhookPayload":{"type":"object","description":"Standard envelope for all webhook deliveries. The `data` field contains event-specific payload.","properties":{"event":{"type":"string","description":"Event type","example":"lead.created"},"timestamp":{"type":"string","format":"date-time","description":"ISO 8601 timestamp of the event"},"tenant_id":{"type":"string","description":"Tenant ID that owns the resource"},"data":{"type":"object","description":"Event-specific data (see event schemas below)"}}}}}}