{"openapi":"3.1.0","info":{"title":"Smartwebchat API","description":"KI-Chatbot-Plattform für Lead-Generierung. Erstelle Chatbots, führe Gespräche, erfasse Leads. Betrieb (Hetzner Online GmbH) und Verarbeitung in der EU.","version":"1.0.0","contact":{"email":"support@smartwebchat.eu","url":"https://smartwebchat.eu"}},"externalDocs":{"description":"Machine-readable entry point for agents: published product data, available agent interfaces, and an explicit status for everything not published yet.","url":"https://smartwebchat.eu/agents/start"},"servers":[{"url":"https://smartwebchat.eu","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API-Schlüssel (swc_...) — im Smartwebchat-Dashboard unter https://smartwebchat.eu/dashboard/agenten erzeugen (nur der Konto-Inhaber). Ein Schlüssel kann auf Nur-Lese-Zugriff beschränkt und mit einem Ablaufdatum versehen werden; ein Nur-Lese-Schlüssel bekommt auf jeden schreibenden Aufruf 403 insufficient_scope; 401 heißt, der Schlüssel fehlt, ist unbekannt oder abgelaufen."}},"parameters":{"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$","maxLength":128},"description":"Optional. Choose a unique value per intended creation and send it again on every retry of that same request: the API then returns the stored first response, marked Idempotency-Replayed: true, instead of creating a second resource. Stored for 24 hours per account and route. The request body is compared byte for byte: the same key with a different body (even a different key order) gives 422. The same key while the first request is still running gives 409 with Retry-After. 5xx responses are not stored; the key is released. POST /api/v1/chatbots/{id}/chat accepts the header only with stream: false — with stream: true (the default) it answers 400 before anything is stored."}},"responses":{"RateLimited":{"description":"Rate limit exceeded: 600 requests per minute per account across all /api/v1/ routes. Wait for the seconds given in Retry-After (60) and retry.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"IdempotencyInProgress":{"description":"A request with this Idempotency-Key is still being processed. Retry after the seconds given in Retry-After (2).","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"IdempotencyMismatch":{"description":"Idempotency-Key was already used with a different request body. Use a new key for a new request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}}},"schemas":{"EventPage":{"type":"object","required":["events","nextCursor","catalogVersion"],"properties":{"events":{"type":"array","items":{"type":"object","required":["id","type","version","occurredAt","chatbotId","data"],"properties":{"id":{"type":"string","description":"Stable per event: <type>:<source id>."},"type":{"type":"string","enum":["lead.created","handover.requested","quota.threshold","payment.failed","job.completed","job.failed"]},"version":{"type":"string"},"occurredAt":{"type":"string","format":"date-time"},"chatbotId":{"type":["string","null"]},"data":{"description":"Identifiers only, never contents. Read contents with the same key via the read path of the event type.","oneOf":[{"title":"lead.created","type":"object","properties":{"leadId":{"type":"string"}},"required":["leadId"],"additionalProperties":false},{"title":"handover.requested","type":"object","properties":{"handoverRequestId":{"type":"string"}},"required":["handoverRequestId"],"additionalProperties":false},{"title":"quota.threshold","type":"object","properties":{"thresholdPercent":{"type":"integer","minimum":1,"maximum":100},"period":{"type":"string"}},"required":["thresholdPercent","period"],"additionalProperties":false},{"title":"payment.failed","type":"object","properties":{},"additionalProperties":false},{"title":"job.completed","type":"object","properties":{"jobId":{"type":"string"},"jobType":{"type":"string","enum":["knowledge_crawl","knowledge_source"]},"status":{"type":"string","enum":["succeeded","partially_succeeded"]},"errorCode":{"type":"null"}},"required":["jobId","jobType","status","errorCode"],"additionalProperties":false},{"title":"job.failed","type":"object","properties":{"jobId":{"type":"string"},"jobType":{"type":"string","enum":["knowledge_crawl","knowledge_source"]},"status":{"type":"string","const":"failed"},"errorCode":{"type":"string"}},"required":["jobId","jobType","status","errorCode"],"additionalProperties":false}]}}}},"nextCursor":{"type":["string","null"],"description":"Pass as cursor to get newer events; null means nothing newer yet."},"catalogVersion":{"type":"string","const":"1.0"}}},"V1Error":{"type":"object","description":"Error body of /api/v1/*. error is the human-readable text; branch on code. Catalog: /agents/errors.","required":["data","error","code"],"properties":{"data":{"type":"null"},"error":{"type":"string"},"code":{"type":"string","enum":["access_inactive","bot_read_only","check_failed","concurrent_change","crawl_blocked_by_robots","crawl_failed","crawl_not_in_preview","credit_insufficient","credits_exhausted","custom_domain_not_set","custom_domain_taken","domain_already_connected","endpoint_retired","file_rejected","file_too_large","idempotency_in_progress","idempotency_key_reused","idempotency_not_supported_for_streaming","insufficient_scope","internal_error","invalid_api_key","invalid_idempotency_key","invalid_input","invalid_link_token","invalid_request","invalid_token","knowledge_none_ready","knowledge_quota_exceeded","knowledge_source_error","message_limit_reached","no_extractable_text","no_web_conversation","not_found","origin_allowlist_empty","origin_rejected","plan_limit_reached","provider_not_allowed_for_healthcare","provider_unavailable","rate_limited","source_not_refreshable","source_processing_failed","target_not_allowed","trial_expired","unsupported_file_type","upstream_failed","upstream_unavailable","url_not_allowed","verified_client_required","whitelabel_required"]}}},"AgentError":{"type":"object","description":"Error body of /api/agents/*. error is the code; message is the human-readable text. Catalog: /agents/errors.","required":["error","message"],"properties":{"error":{"type":"string","enum":["handoff_disabled","handoff_no_longer_valid","idempotency_key_reused","invalid_idempotency_key","invalid_input","invalid_json","payload_too_large","quote_unavailable","rate_limited","status_unavailable","unavailable"]},"message":{"type":"string"}}},"Diagnosis":{"type":"object","required":["chatbotId","ok","complete","findings"],"properties":{"chatbotId":{"type":"string"},"ok":{"type":"boolean"},"complete":{"type":"boolean"},"findings":{"type":"array","items":{"type":"object","required":["code","severity","remedy"],"properties":{"code":{"type":"string","enum":["access_inactive","message_limit_reached","credits_exhausted","provider_unavailable","provider_not_allowed_for_healthcare","origin_rejected","knowledge_source_error","check_failed","origin_allowlist_empty","knowledge_none_ready","no_web_conversation"]},"severity":{"type":"string","enum":["error","warning","info"]},"remedy":{"type":"string"},"details":{"type":"object","additionalProperties":true}}}}}},"FitAssessment":{"type":"object","description":"Vendor self-assessment per the locked fit contract. Self-asserted, not independently verified; can be not_fit.","required":["schema_version","fit","reasons","limitations","recommended_plan","relevant_urls","trial_url","provenance"],"properties":{"schema_version":{"type":"string","enum":["1.0"]},"fit":{"type":"string","enum":["good_fit","partial_fit","not_fit","needs_review"]},"reasons":{"type":"array","items":{"type":"string"}},"limitations":{"type":"array","items":{"type":"string"}},"recommended_plan":{"type":"string","enum":["business","agency","white_label","none","needs_review"]},"relevant_urls":{"type":"array","items":{"type":"string","format":"uri"}},"trial_url":{"type":["string","null"],"format":"uri"},"provenance":{"type":"object","properties":{"self_asserted":{"type":"boolean","enum":[true]},"independently_verified":{"type":"boolean","enum":[false]},"source":{"type":"string","format":"uri"}}}}},"Quote":{"type":"object","description":"Monthly net quote in EUR from the product-truth layer, each line with its source fact id; white label is 'custom'. No checkout link.","required":["schema_version","kind","plan","currency","tax","checkout_note","provenance"],"properties":{"schema_version":{"type":"string","enum":["1.0"]},"kind":{"type":"string","enum":["priced","custom"]},"plan":{"type":"string","enum":["business","agency","white_label"]},"currency":{"type":"string","enum":["EUR"]},"tax":{"type":"string","enum":["net"]},"billing":{"type":"string","enum":["monthly"]},"included":{"type":"object"},"line_items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"quantity":{"type":"number"},"unit":{"type":"string"},"unit_net_eur":{"type":"number"},"total_net_eur":{"type":"number"},"source_fact_id":{"type":"string"}}}},"total_monthly_net_eur":{"type":"number"},"price":{"type":"string","enum":["custom"]},"self_service":{"type":"boolean"},"assumptions":{"type":"array","items":{"type":"string"}},"checkout_note":{"type":"string"},"provenance":{"type":"object"}}},"HandoverRequest":{"type":"object","properties":{"id":{"type":"string"},"chatbotId":{"type":"string"},"userId":{"type":"string"},"sessionId":{"type":"string"},"customerName":{"type":"string","nullable":true},"customerEmail":{"type":"string","nullable":true},"reason":{"type":"string","description":"z.B. 'User explicit request', 'Bot uncertainty'. Wird 30 Tage nach Erstellung auf 'User explicit request' zurückgesetzt (DAT-01)."},"lastMessages":{"type":"array","description":"Gesprächsauszug zur Übergabe. Wird 30 Tage nach Erstellung geleert und liefert danach dauerhaft `[]` (DAT-01). Die Zeile selbst bleibt bestehen, solange die je Assistent eingestellte Aufbewahrungsfrist läuft (Vorgabe 365 Tage) — AUSSER es bleibt nach der Leerung nichts Identifizierendes übrig (kein `customerName`, kein `customerEmail`, keine `resolutionNotes`): Dann verschwindet die Zeile schon nach 30 Tagen. Das betrifft die über Schluesselwoerter ausgeloesten Uebergaben.","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"type":"string"}}}},"status":{"type":"string","enum":["requested","notified","accepted","resolved","cancelled"]},"assignedToUserId":{"type":"string","nullable":true},"acceptedAt":{"type":"string","format":"date-time","nullable":true},"resolvedAt":{"type":"string","format":"date-time","nullable":true},"resolutionNotes":{"type":"string","nullable":true},"notificationChannel":{"type":"string","enum":["email","slack","webhook"]},"notificationSentAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"HandoverSettings":{"type":"object","properties":{"chatbotId":{"type":"string"},"enabled":{"type":"boolean"},"notificationEmail":{"type":"string","nullable":true},"slackWebhookUrl":{"type":"string","nullable":true},"businessHours":{"type":"object","description":"Keys: mo/di/mi/do/fr/sa/so. Wert: [startHour, endHour] oder null (geschlossen)."},"outsideHoursMessage":{"type":"string"},"autoHandoverKeywords":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"Booking":{"type":"object","properties":{"id":{"type":"string"},"chatbotId":{"type":"string"},"userId":{"type":"string"},"customerName":{"type":"string"},"customerEmail":{"type":"string"},"customerPhone":{"type":"string","nullable":true},"service":{"type":"string","description":"Gewünschter Service, z.B. 'Probestunde', 'Erstberatung'"},"requestedAtText":{"type":"string","description":"Terminwunsch als freier Text, z.B. 'Donnerstag Vormittag'"},"requestedAtIso":{"type":"string","format":"date-time","nullable":true},"notes":{"type":"string"},"status":{"type":"string","enum":["new","forwarded","confirmed","cancelled"]},"sourceSessionId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"KnowledgeSourceInput":{"description":"One of four forms, chosen by type. A file travels as base64 so that a retry with the same Idempotency-Key has the same body.","oneOf":[{"type":"object","required":["type","url"],"properties":{"type":{"type":"string","enum":["url"]},"url":{"type":"string"}}},{"type":"object","required":["type","text"],"properties":{"type":{"type":"string","enum":["text"]},"text":{"type":"string"}}},{"type":"object","required":["type","question","answer"],"properties":{"type":{"type":"string","enum":["faq"]},"question":{"type":"string"},"answer":{"type":"string"}}},{"type":"object","required":["type","filename","content_base64"],"properties":{"type":{"type":"string","enum":["file"]},"filename":{"type":"string"},"content_base64":{"type":"string","contentEncoding":"base64"}}}]},"Job":{"type":"object","description":"A long-running job, projected from the crawl or source state. running means not finished yet; it is not a promise that the job will finish. A crawl whose processing failed for good is marked failed with error_code crawl_failed, after its retries. No content, no URLs.","required":["id","type","status","chatbot_id","created_at","updated_at","error_code"],"properties":{"id":{"type":"string","description":"crawl_<uuid> or source_<uuid>"},"type":{"type":"string","enum":["knowledge_crawl","knowledge_source"]},"status":{"type":"string","enum":["running","awaiting_confirmation","succeeded","partially_succeeded","failed"]},"chatbot_id":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"error_code":{"type":["string","null"],"description":"Code from /agents/errors when status is failed; otherwise null"},"progress":{"type":"object","description":"Crawl jobs only","properties":{"discovered":{"type":"integer"},"pending":{"type":"integer"},"processing":{"type":"integer"},"ready":{"type":"integer"},"failed":{"type":"integer"}}}}},"Order":{"type":"object","properties":{"id":{"type":"string","description":"Digistore24 order id"},"kind":{"type":"string","enum":["subscription","seat","assistant","credit"]},"status":{"type":"string","enum":["paid","payment_failed","cancelled","refunded","chargeback"]},"fulfillment":{"type":"string","enum":["applied","pending"]},"amount":{"type":["string","null"]},"currency":{"type":["string","null"]},"payments":{"type":"integer","minimum":0},"firstEventAt":{"type":"string","format":"date-time"},"lastEventAt":{"type":"string","format":"date-time"}}},"Usage":{"type":"object","properties":{"messages":{"type":["object","null"],"description":"Message counter of the current billing period; null if it cannot be read","properties":{"used":{"type":"integer","minimum":0},"limit":{"type":"integer","minimum":0}}},"credits":{"type":"object","properties":{"balanceMicros":{"type":"integer","description":"Purchased credit in micro-euros"},"includedMicros":{"type":"integer","description":"Included monthly budget in micro-euros"},"lowBalanceThresholdMicros":{"type":["integer","null"]}}}}},"Subscription":{"type":"object","properties":{"plan":{"type":"string"},"status":{"type":"string","enum":["trialing","active","cancelled","deleted"]},"activeUntil":{"type":["string","null"],"format":"date-time"},"trialEndsAt":{"type":["string","null"],"format":"date-time","description":"Only while trialing"},"purchasedSeats":{"type":"integer","minimum":0},"purchasedAssistants":{"type":"integer","minimum":0},"sponsored":{"type":"boolean"}}},"Team":{"type":"object","properties":{"plan":{"type":"string"},"purchasedSeats":{"type":"integer","minimum":0},"seatLimit":{"type":"integer","minimum":0},"seatUsage":{"type":"integer","minimum":0},"members":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"email":{"type":"string"},"role":{"type":"string","enum":["owner","member"]}}}},"invites":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"}}}}}},"Account":{"type":"object","properties":{"company":{"type":"string"},"legalForm":{"type":["string","null"],"description":"Legal form code"},"legalFormVariant":{"type":["string","null"]},"address":{"type":"object","properties":{"street":{"type":["string","null"]},"zip":{"type":["string","null"]},"city":{"type":["string","null"]},"country":{"type":["string","null"]}}},"vatId":{"type":["string","null"]},"phone":{"type":["string","null"]}}},"CheckoutPreparation":{"type":"object","description":"Result of prepareCheckout. Creates nothing; only a person can place the order via human_confirmation_url.","properties":{"schema_version":{"type":"string","enum":["1.0"]},"kind":{"type":"string","enum":["self_service","not_self_service"]},"plan":{"type":"string","enum":["business","agency","white_label"]},"locale":{"type":"string","description":"Language actually used for the links (fallback de)"},"prepared_at":{"type":"string","format":"date-time"},"quote":{"type":"object","description":"Same contract as quotePlan"},"contract":{"type":"object","properties":{"terms_version":{"type":"string"},"privacy_version":{"type":"string"},"dpa_version":{"type":"string"}}},"steps":{"type":"array","items":{"type":"string"}},"human_confirmation_url":{"type":["string","null"],"format":"uri"},"confirmation_unavailable_reason":{"type":["string","null"],"enum":["checkout_not_live","no_self_service",null]},"registration_url":{"type":"string","format":"uri"},"order_note":{"type":["string","null"]}}},"Chatbot":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"businessName":{"type":"string"},"websiteUrl":{"type":"string"},"industry":{"type":"string"},"description":{"type":"string"},"faqs":{"type":"array","items":{"type":"object","properties":{"question":{"type":"string"},"answer":{"type":"string"}}}},"greeting":{"type":"string"},"personality":{"type":"string","enum":["freundlich","professionell","locker"]},"llmProvider":{"type":"string","enum":["openai","mistral"],"description":"Welcher LLM-Provider den Bot bedient. Vorgabe: mistral; dessen Standardmodell ist mistral-small-latest (EU-Hosting)."},"createdAt":{"type":"string","format":"date-time"}}},"Lead":{"type":"object","properties":{"id":{"type":"string"},"chatbotId":{"type":"string"},"name":{"type":"string","nullable":true},"email":{"type":"string","nullable":true},"phone":{"type":"string","nullable":true},"message":{"type":"string","nullable":true},"type":{"type":"string","enum":["contact","appointment","callback"]},"status":{"type":"string","enum":["new","contacted","closed"]},"createdAt":{"type":"string","format":"date-time"}}},"ProactiveTrigger":{"type":"object","properties":{"id":{"type":"string"},"chatbotId":{"type":"string"},"userId":{"type":"string"},"name":{"type":"string"},"triggerType":{"type":"string","enum":["time_on_page","exit_intent","scroll_depth","page_view_count","inactivity"]},"conditionValue":{"type":"object","description":"Typ-abhängiger Bedingungswert: { seconds } | { percent } | { count } | {}"},"targetPagePattern":{"type":"string","description":"URL-Glob-Pattern, z.B. * oder /pricing/*"},"messageTemplate":{"type":"string"},"cooldownMinutes":{"type":"integer","description":"Mindestabstand zwischen zwei Fires derselben Session"},"enabled":{"type":"boolean"},"priority":{"type":"integer","description":"Höhere Zahl = höhere Priorität"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}},"paths":{"/api/status":{"get":{"summary":"Current service status: components, incidents and planned maintenance","description":"Open, no API key. Reports the current state of the product components, open and recently ended incidents and planned maintenance. It names no internal checks, hosts or error texts and makes no availability or response-time commitment. Not a health check for monitoring.","operationId":"getServiceStatus","security":[],"responses":{"200":{"description":"Current status","content":{"application/json":{"schema":{"type":"object","required":["schema_version","status","timestamp","components","incidents","maintenance","note"],"properties":{"schema_version":{"type":"string"},"status":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"components":{"type":"array","items":{"type":"object"}},"incidents":{"type":"array","items":{"type":"object"}},"maintenance":{"type":"array","items":{"type":"object"}},"note":{"type":"string"}}}}}},"503":{"description":"The status could not be determined; code status_unavailable, retry after Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}}}}},"/api/agents/fit":{"post":{"summary":"Fit assessment for a described business (vendor self-assessment, can say no)","description":"Deterministic assessment per the locked fit contract. Reads approved product facts only; never fetches the described website. primary_need is one of website_assistant, customer_service, lead_generation, appointments, faq, multilingual, agency, white_label, full_omnichannel_helpdesk. Rate limited per IP.","operationId":"assessFit","security":[],"responses":{"200":{"description":"Fit assessment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FitAssessment"}}}},"400":{"description":"Invalid input — issues list with path, message, code","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}},"429":{"description":"Rate limited — Retry-After: 60","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}}},"x-mcp-tool":"smartwebchat_get_fit","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"market":{"type":"string","minLength":2,"maxLength":64,"description":"Country or market of the business, e.g. 'DE', 'de-AT', 'NL', 'US'. Free text; only the language part is matched against the published website languages."},"locale":{"type":"string","maxLength":35,"pattern":"^[A-Za-z]{2,3}(?:[-_][A-Za-z0-9]{1,8})*$","description":"Language tag for the returned URLs, e.g. 'en', 'fr-CA', 'it', 'pt-BR'. Any well-formed tag is accepted; languages without a published website fall back to 'de'. The language never changes the verdict."},"primary_need":{"type":"string","enum":["website_assistant","customer_service","lead_generation","appointments","faq","multilingual","agency","white_label","full_omnichannel_helpdesk"],"description":"What the business mainly needs the assistant for."},"website_platform":{"type":"string","minLength":1,"maxLength":100,"description":"Website system as stated by the caller, e.g. 'wordpress'. Echoed back only; never fetched or verified."},"number_of_client_assistants":{"type":"integer","minimum":1,"maximum":10000,"description":"How many separate businesses or client assistants are to be served. More than one points to the agency plan."},"requires_white_label":{"type":"boolean","description":"Smartwebchat branding must be removed."},"requires_custom_widget_domain":{"type":"boolean","description":"The widget must run on the caller's own domain."},"requires_full_omnichannel_inbox":{"type":"boolean","description":"A full omnichannel inbox or helpdesk across channels is required."},"requires_direct_calendar_write":{"type":"boolean","description":"The assistant must write appointments directly into a calendar."},"sensitive_professional_context":{"type":"boolean","description":"The business handles sensitive professional data (e.g. health, legal, tax)."},"requested_ai_provider":{"type":"string","enum":["default","mistral","openai","anthropic","other"],"description":"The language model provider the caller wants. 'default' is the vendor's EU standard configuration."}},"required":["primary_need"],"additionalProperties":false}}}}}},"/api/agents/quote":{"post":{"summary":"Monthly net quote for a plan with add-ons, each figure with its source","description":"Prices business or agency with optional add-ons and message overage; white label returns price 'custom'. No checkout link is issued. Rate limited per IP.","operationId":"quotePlan","security":[],"responses":{"200":{"description":"Quote","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Quote"}}}},"400":{"description":"Invalid input — issues list with path, message, code","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}},"429":{"description":"Rate limited — Retry-After: 60","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}},"503":{"description":"Quote unavailable — a price fact is not approved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}}},"x-mcp-tool":"smartwebchat_get_quote","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string","enum":["business","agency","white_label"],"description":"Plan to quote. 'white_label' returns price 'custom' without a calculation."},"additional_assistants":{"type":"integer","minimum":0,"maximum":1000,"description":"Additional assistants beyond the plan's included number (integer, 0 or more)."},"additional_seats":{"type":"integer","minimum":0,"maximum":1000,"description":"Additional team seats beyond the plan's included number (integer, 0 or more)."},"expected_messages_per_month":{"type":"integer","minimum":0,"maximum":10000000,"description":"Expected messages per month; overage above the included quota is priced per 1,000 messages."}},"required":["plan"],"additionalProperties":false}}}}}},"/api/agents/handoff":{"post":{"summary":"Prepare a single-use sign-up link for a person (no account or trial is created)","description":"Returns handoff_url and expires_in_seconds. The link carries language, industry and recommended plan into registration and onboarding and works once. The account and the trial are created only when the person signs up. Rate limited to 20 requests per hour per IP, REST and MCP together. Disabled by default: 503 with error handoff_disabled; /agents/start shows the current status.","operationId":"prepareAgentHandoff","security":[],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,128}$","maxLength":128},"description":"Send the same key on every retry of the same request: while the link is valid (up to 15 minutes) the retry returns the same handoff_url, marked Idempotency-Replayed: true. The same key with a different body gives 422."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"locale":{"type":"string","minLength":2,"maxLength":35,"description":"Language of the sign-up page, for example 'en'. Unsupported languages fall back to 'de'."},"industry_key":{"type":"string","enum":["anwaelte","apotheken","arztpraxen","fahrschulen","friseure","handwerker","heilmittelpraxen","hotels","immobilien","kfz-werkstaetten","kosmetikstudios","pflegedienste","pflegeheime","physiotherapie","restaurants","sanitaetshaeuser","steuerberater","tieraerzte","versicherungsmakler","zahnaerzte"],"description":"Industry of the business, one of `how_to_test.agent_demo_contract.industries` in /agents/start."},"recommended_plan":{"type":"string","enum":["business","agency","white_label"],"description":"Plan you recommend: business, agency, white_label. Only plans with a trial preselect the trial type; the person can change it."},"demo_session_id":{"type":"string","description":"Optional demo session id from the scanner demo; its context is restored after sign-up."}},"additionalProperties":false}}}},"responses":{"200":{"description":"Replay of the same request (Idempotency-Replayed: true)."},"201":{"description":"handoff_url, expires_in_seconds, single_use."},"400":{"description":"invalid_json, invalid_input or invalid_idempotency_key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}},"409":{"description":"handoff_no_longer_valid: send a new Idempotency-Key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}},"413":{"description":"payload_too_large.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}},"422":{"description":"idempotency_key_reused.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}},"429":{"description":"rate_limited — Retry-After: 3600","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}},"503":{"description":"handoff_disabled or unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}}},"x-mcp-tool":"smartwebchat_prepare_handoff"}},"/api/agents/prepare-checkout":{"post":{"summary":"Prepare a purchase for a person: quote, contract versions, steps and the confirmation URL","operationId":"prepareCheckout","description":"Open, no API key. Creates nothing: no order, no account, no trial. Only a person can place the order, locale follows the same rule as assessFit: any well-formed tag, fallback 'de' for languages without a published website; the response field locale is the language used for the checkout link. by opening human_confirmation_url in a browser. human_confirmation_url is null for white_label (no self-service) and when checkout is not live for the language; use registration_url then. The confirmation link covers the plan; additional assistants and seats are bought after sign-up. Rate limit 60 requests per minute per IP.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string","enum":["business","agency","white_label"],"description":"Plan to quote. 'white_label' returns price 'custom' without a calculation."},"additional_assistants":{"type":"integer","minimum":0,"maximum":1000,"description":"Additional assistants beyond the plan's included number (integer, 0 or more)."},"additional_seats":{"type":"integer","minimum":0,"maximum":1000,"description":"Additional team seats beyond the plan's included number (integer, 0 or more)."},"expected_messages_per_month":{"type":"integer","minimum":0,"maximum":10000000,"description":"Expected messages per month; overage above the included quota is priced per 1,000 messages."},"locale":{"type":"string","maxLength":35,"pattern":"^[A-Za-z]{2,3}(?:[-_][A-Za-z0-9]{1,8})*$","description":"Language tag, e.g. 'en', 'fr-CA', 'it'. Any well-formed tag is accepted; languages without a published website fall back to 'de'. The response field locale names the language actually used."}},"required":["plan"],"additionalProperties":false}}}},"responses":{"200":{"description":"The preparation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutPreparation"}}}},"400":{"description":"invalid_json or invalid_input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}},"429":{"description":"rate_limited; see Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}},"503":{"description":"quote_unavailable: a price fact is not published","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentError"}}}}}}},"/api/v1/api-key":{"post":{"summary":"Stillgelegt — Schlüssel entstehen im Dashboard","description":"Bis zum 25.08.2026 erzeugte dieser Endpunkt ck_-Schlüssel ohne Umfang und ohne Ablaufdatum. Er antwortet jetzt immer mit 410. Schlüssel entstehen im Smartwebchat-Dashboard unter https://smartwebchat.eu/dashboard/agenten — dort wählt man Nur-Lese-Zugriff oder Vollzugriff und eine Gültigkeit.","operationId":"generateApiKey","deprecated":true,"security":[],"responses":{"410":{"description":"Gone — create keys in the dashboard instead","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}}}}},"/api/v1/chatbots":{"get":{"summary":"List chatbots","operationId":"listChatbots","responses":{"200":{"description":"Array of chatbots"},"429":{"$ref":"#/components/responses/RateLimited"}},"x-mcp-tool":"smartwebchat_list_chatbots"},"post":{"summary":"Create chatbot","operationId":"createChatbot","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","businessName","industry"],"properties":{"name":{"type":"string"},"businessName":{"type":"string"},"websiteUrl":{"type":"string"},"industry":{"type":"string"},"description":{"type":"string"},"faqs":{"type":"array","items":{"type":"object","properties":{"question":{"type":"string"},"answer":{"type":"string"}}}},"greeting":{"type":"string"},"personality":{"type":"string","enum":["freundlich","professionell","locker"]},"llmProvider":{"type":"string","enum":["openai","mistral"],"default":"mistral"}}}}}},"responses":{"200":{"description":"Created chatbot"},"409":{"$ref":"#/components/responses/IdempotencyInProgress"},"422":{"$ref":"#/components/responses/IdempotencyMismatch"},"429":{"$ref":"#/components/responses/RateLimited"}},"x-mcp-tool":"smartwebchat_create_chatbot","parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/api/v1/chatbots/{id}":{"get":{"summary":"Get chatbot details","operationId":"getChatbot","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Chatbot with stats"},"429":{"$ref":"#/components/responses/RateLimited"}}},"put":{"summary":"Update chatbot","operationId":"updateChatbot","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Updated chatbot"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"summary":"Delete chatbot","operationId":"deleteChatbot","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deletion confirmed"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/chat":{"post":{"summary":"Send message to chatbot","operationId":"chatWithBot","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string","maxLength":2000},"sessionId":{"type":"string"},"stream":{"type":"boolean","default":true}}}}}},"responses":{"200":{"description":"Streaming text response or JSON with { reply, sessionId }"},"409":{"$ref":"#/components/responses/IdempotencyInProgress"},"422":{"$ref":"#/components/responses/IdempotencyMismatch"},"429":{"$ref":"#/components/responses/RateLimited"}},"x-mcp-tool":"smartwebchat_chat"}},"/api/v1/chatbots/{id}/knowledge/sources":{"get":{"summary":"List the knowledge sources of a chatbot","operationId":"listKnowledgeSources","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Chatbot ID"}],"responses":{"200":{"description":"Array of knowledge sources (id, source_type, status, error_code, token_count, byte_size, crawl_id, created_at, updated_at). No content, no names, no free text."},"404":{"description":"Chatbot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"summary":"Add a knowledge source (file as base64, URL, text or FAQ)","description":"Same quota, credit check, URL safety and file checks as the dashboard. Processing runs in the background; the response carries the job to poll at GET /api/v1/jobs/{jobId}.","operationId":"addKnowledgeSource","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Chatbot ID"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeSourceInput"}}}},"responses":{"202":{"description":"Source accepted; data.source and data.job"},"400":{"description":"Invalid input or URL not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"402":{"description":"Knowledge quota exceeded or credit insufficient","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"409":{"$ref":"#/components/responses/IdempotencyInProgress"},"413":{"description":"file_too_large: the JSON body may be at most 10223616 bytes, with or without Content-Length (checked before the body is used), so files up to 7618560 bytes always fit as base64, below the plan's file limit where that is smaller.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"415":{"description":"Unsupported file type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"422":{"$ref":"#/components/responses/IdempotencyMismatch"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/knowledge/sources/{sourceId}":{"get":{"summary":"Read a knowledge source (without its content)","operationId":"getKnowledgeSource","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Chatbot ID"},{"name":"sourceId","in":"path","required":true,"schema":{"type":"string"},"description":"Knowledge source ID"}],"responses":{"200":{"description":"Same fields as in the list: no content, no names, no free text; error_code from /agents/errors when status is error"},"404":{"description":"Source not found for this chatbot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"summary":"Delete a knowledge source","operationId":"deleteKnowledgeSource","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Chatbot ID"},{"name":"sourceId","in":"path","required":true,"schema":{"type":"string"},"description":"Knowledge source ID"}],"responses":{"200":{"description":"Deleted"},"404":{"description":"Source not found for this chatbot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/knowledge/sources/{sourceId}/refresh":{"post":{"summary":"Refresh a URL source","operationId":"refreshKnowledgeSource","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Chatbot ID"},{"name":"sourceId","in":"path","required":true,"schema":{"type":"string"},"description":"Knowledge source ID"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"202":{"description":"Refresh started; data.job"},"400":{"description":"Only URL sources can be refreshed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"402":{"description":"Knowledge quota used up (knowledge_quota_exceeded) or credit insufficient (credit_insufficient)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Source not found for this chatbot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"409":{"$ref":"#/components/responses/IdempotencyInProgress"},"422":{"$ref":"#/components/responses/IdempotencyMismatch"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/knowledge/crawl":{"post":{"summary":"Start a website crawl","description":"Discovers pages of the website, then waits for confirmation (job status awaiting_confirmation). Same URL safety, quota and crawl-start limit as the dashboard.","operationId":"startKnowledgeCrawl","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Chatbot ID"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string"}}}}}},"responses":{"202":{"description":"Crawl started; data.job"},"400":{"description":"URL missing or not allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"402":{"description":"Knowledge quota used up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"409":{"$ref":"#/components/responses/IdempotencyInProgress"},"422":{"$ref":"#/components/responses/IdempotencyMismatch"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/knowledge/crawl/{crawlId}":{"get":{"summary":"Read a crawl: its job and the discovered pages (id, status, depth; no URLs)","operationId":"getKnowledgeCrawl","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Chatbot ID"},{"name":"crawlId","in":"path","required":true,"schema":{"type":"string"},"description":"Crawl ID"}],"responses":{"200":{"description":"data.job, data.pages, data.estimated_cost_micros"},"404":{"description":"Crawl not found for this chatbot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/knowledge/crawl/{crawlId}/confirm":{"post":{"summary":"Confirm a crawl and import its pages","description":"409 has two causes, told apart by error.code: idempotency_in_progress, or crawl_not_in_preview when the crawl is not waiting for confirmation (read the job first).","operationId":"confirmKnowledgeCrawl","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Chatbot ID"},{"name":"crawlId","in":"path","required":true,"schema":{"type":"string"},"description":"Crawl ID"},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"202":{"description":"Import started; data.job"},"404":{"description":"Crawl not found for this chatbot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"409":{"$ref":"#/components/responses/IdempotencyInProgress"},"422":{"$ref":"#/components/responses/IdempotencyMismatch"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/jobs/{jobId}":{"get":{"summary":"Status of a long-running job (website crawl or source processing)","operationId":"getJob","parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"},"description":"crawl_<uuid> or source_<uuid>"}],"responses":{"200":{"description":"Job","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"404":{"description":"Job not found for this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/leads":{"get":{"summary":"List leads for chatbot","operationId":"getLeads","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Array of leads"},"429":{"$ref":"#/components/responses/RateLimited"}},"x-mcp-tool":"smartwebchat_get_leads"}},"/api/v1/chatbots/{id}/leads/{leadId}":{"patch":{"summary":"Update lead status","operationId":"updateLeadStatus","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Chatbot ID"},{"name":"leadId","in":"path","required":true,"schema":{"type":"string"},"description":"Lead ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["new","contacted","closed"]}}}}}},"responses":{"200":{"description":"Updated lead"},"400":{"description":"Invalid status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot or lead not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}},"x-mcp-tool":"smartwebchat_update_lead"},"delete":{"summary":"Delete a single lead","operationId":"deleteLead","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Chatbot ID"},{"name":"leadId","in":"path","required":true,"schema":{"type":"string"},"description":"Lead ID"}],"responses":{"200":{"description":"Lead deleted"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot or lead not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/installation":{"get":{"summary":"Installation status of a chatbot: website conversations and origins","description":"Read-only; a read key is enough. webConversationSeen shows that someone chatted over the website chat (the onboarding test chat counts too) and does not prove an installation. Accepted origins are not recorded; originsAllowed is the configuration, originsRejected the most recent refused origins (capped; forgeable outside a browser).","operationId":"getChatbotInstallation","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Installation status"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found (also for a chatbot of another account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"A status source could not be read; no partial answer is given","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}}}}},"/api/v1/chatbots/{id}/diagnose":{"get":{"summary":"Diagnose why a chatbot does not answer","description":"Read-only; a read key is enough. findings lists { code, severity, remedy, details } — codes and remedies are in the error catalog. ok is false when a finding has severity error (visitors get no answer); complete is false when a check could not be read (CHECK_FAILED).","operationId":"diagnoseChatbot","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Diagnosis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Diagnosis"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found (also for a chatbot of another account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}},"x-mcp-tool":"smartwebchat_diagnose"}},"/api/v1/chatbots/{id}/branding":{"get":{"summary":"Branding of a chatbot: colors, Smartwebchat notice, legal links","description":"Read-only; a read key is enough. The logo is managed in the dashboard.","operationId":"getChatbotBranding","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Branding"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found (also for a chatbot of another account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"summary":"Change branding (partial update)","description":"Partial update: only the fields you send change; {} changes nothing. hidePoweredBy true requires a white-label agreement (403 whitelabel_required); the plan alone does not grant it. privacyUrl and imprintUrl take an http(s) URL of at most 500 characters, or an empty value to remove the link.","operationId":"updateChatbotBranding","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"primaryColor":{"type":"string","pattern":"^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"},"accentColor":{"type":"string","pattern":"^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"},"hidePoweredBy":{"type":"boolean"},"privacyUrl":{"type":["string","null"],"maxLength":500},"imprintUrl":{"type":["string","null"],"maxLength":500}}}}}},"responses":{"200":{"description":"Branding after the change"},"400":{"description":"A field is invalid, or the body is not a JSON object","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"401":{"description":"Invalid or missing API key, or a read key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"403":{"description":"whitelabel_required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found (also for a chatbot of another account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/custom-domain":{"get":{"summary":"Custom widget domain of a chatbot","description":"Read-only; a read key is enough.","operationId":"getChatbotCustomDomain","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"customDomain and customDomainVerified"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found (also for a chatbot of another account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"put":{"summary":"Set the custom widget domain","description":"Requires a white-label agreement (403 whitelabel_required). The domain may be set before its DNS record exists; it must not resolve to a private or internal address (400 target_not_allowed). Setting a domain resets verification and adds https://<domain> to the allowed origins. Use DELETE to remove it.","operationId":"setChatbotCustomDomain","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["customDomain"],"properties":{"customDomain":{"type":"string","maxLength":253}}}}}},"responses":{"200":{"description":"customDomain and customDomainVerified (false until verified)"},"400":{"description":"Invalid domain, or target_not_allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"401":{"description":"Invalid or missing API key, or a read key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"403":{"description":"whitelabel_required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found (also for a chatbot of another account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"409":{"description":"custom_domain_taken","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"summary":"Remove the custom widget domain","description":"Works without a white-label agreement, so a lost agreement can be cleaned up.","operationId":"removeChatbotCustomDomain","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"customDomain null"},"401":{"description":"Invalid or missing API key, or a read key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found (also for a chatbot of another account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/custom-domain/verify":{"post":{"summary":"Check the DNS record of the custom domain now","description":"Checks the DNS record now and returns the result synchronously (no job). A failed check is 200 with verified false; reasonCode is cname_mismatch, ip_mismatch or not_resolving. No domain set: 400 custom_domain_not_set.","operationId":"verifyChatbotCustomDomain","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"responses":{"200":{"description":"verified, via, reasonCode, reason, resolvedHostname, resolvedIps, tlsReady"},"400":{"description":"custom_domain_not_set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"401":{"description":"Invalid or missing API key, or a read key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found (also for a chatbot of another account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"409":{"$ref":"#/components/responses/IdempotencyInProgress"},"422":{"$ref":"#/components/responses/IdempotencyMismatch"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/webhooks":{"get":{"summary":"List the webhooks of a chatbot","description":"Read-only; a read key is enough. Never contains secrets.","operationId":"listChatbotWebhooks","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"webhooks: { id, chatbotId, name, url, active, createdAt }[]. active false: the webhook is switched off and receives no deliveries. Webhooks created by an AI agent are switched off when that agent's authorization ends. A switched-off webhook cannot be re-enabled; delete it and create a new one if needed."},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found (also for a chatbot of another account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"summary":"Create a webhook","description":"The response contains the signing secret exactly once (secretShown true). A retry with the same Idempotency-Key returns the same webhook with secret null and secretShown false; if secretShown is false, delete and recreate the webhook to get a new secret. The target must resolve to a public address (400 target_not_allowed).","operationId":"createChatbotWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","url"],"properties":{"name":{"type":"string","maxLength":100},"url":{"type":"string","format":"uri"}}}}}},"responses":{"201":{"description":"Webhook created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"chatbotId":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"},"active":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"secret":{"type":["string","null"],"description":"Signing secret; only in the first response"},"secretShown":{"type":"boolean","description":"true in the first response; false on an idempotent retry. If secretShown is false, delete and recreate the webhook to get a new secret."}}},"error":{"type":"null"}}}}}},"400":{"description":"Invalid name or url, or target_not_allowed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"401":{"description":"Invalid or missing API key, or a read key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found (also for a chatbot of another account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"409":{"$ref":"#/components/responses/IdempotencyInProgress"},"422":{"$ref":"#/components/responses/IdempotencyMismatch"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/webhooks/{webhookId}":{"delete":{"summary":"Delete a webhook","description":"Only a webhook of this chatbot; any other id returns 404.","operationId":"deleteChatbotWebhook","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"deleted: true"},"401":{"description":"Invalid or missing API key, or a read key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot or webhook not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/embed":{"get":{"summary":"Embed snippet of a chatbot","description":"Read-only; a read key is enough. Returns the same embed snippet the dashboard shows.","operationId":"getChatbotEmbed","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"botId, scriptUrl, snippet"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found (also for a chatbot of another account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/origins":{"get":{"summary":"Allowed origins of a chatbot","description":"Read-only; a read key is enough.","operationId":"getChatbotOrigins","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"allowedOrigins"},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found (also for a chatbot of another account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"put":{"summary":"Replace the allowed origins","description":"Replaces the whole list (max twenty entries), as the dashboard does. Removing https://<custom domain> is allowed, as in the dashboard. During the trial a domain another account has connected is refused (409 domain_already_connected).","operationId":"setChatbotOrigins","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["allowedOrigins"],"properties":{"allowedOrigins":{"type":"array","maxItems":20,"items":{"type":"string"}}}}}}},"responses":{"200":{"description":"allowedOrigins after the change"},"400":{"description":"Not an array, too many, invalid or too broad entries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"401":{"description":"Invalid or missing API key, or a read key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found (also for a chatbot of another account)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"409":{"description":"domain_already_connected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/chatbots/{id}/conversations":{"get":{"summary":"List conversations grouped by session","operationId":"getConversations","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Array of conversations"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/bookings":{"get":{"summary":"List bookings (all chatbots of the authenticated user)","operationId":"listBookings","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"maximum":200}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Array of bookings"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/bookings/{id}":{"get":{"summary":"Get booking by ID","operationId":"getBooking","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Booking object"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Booking not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"summary":"Update booking status","operationId":"updateBookingStatus","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["new","forwarded","confirmed","cancelled"]}}}}}},"responses":{"200":{"description":"Updated booking"},"400":{"description":"Invalid status value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Booking not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/events":{"get":{"summary":"List the events of the account (new lead, handover requested, credit threshold, missed payment)","operationId":"listEvents","description":"Oldest first, paged with cursor. Events appear with a delay of 5 seconds. Events older than 30 days are not returned; if you poll less often, you lose events — use the webhooks for complete delivery. Events may be delivered more than once: quota.threshold may disappear and reappear with the same id if the warning mail failed (deduplicate by id). payment.failed: repeated notifications for the same payment transaction within 48 hours are delivered once; a later failure of the same transaction is a new event; without a transaction id it may be delivered more than once, with different ids. Catalog version 1.0; the schema of each type is listed under webhooks.","parameters":[{"name":"type","in":"query","required":false,"description":"Filter by event type; may be repeated. Without it, all types.","schema":{"type":"array","items":{"type":"string","enum":["lead.created","handover.requested","quota.threshold","payment.failed","job.completed","job.failed"]}},"style":"form","explode":true},{"name":"cursor","in":"query","required":false,"description":"nextCursor of the previous page.","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"One page of events","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/EventPage"},"error":{"type":"null"}}}}}},"400":{"description":"Unknown type, invalid cursor or limit out of range","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"The events could not be read; retry later","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}}}}},"/api/v1/orders":{"get":{"summary":"List the orders of the account (subscription, seats, assistants, credit)","operationId":"listOrders","description":"Derived from the payment notifications of Digistore24. Newest first by last event. amount and currency are passed through as delivered by the payment provider (strings, not parsed). fulfillment is pending while a notification could not be applied yet; the provider retries it. Invoices are issued by Digistore24 and are not available via this API.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Orders","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"orders":{"type":"array","items":{"$ref":"#/components/schemas/Order"}},"truncated":{"type":"boolean"}}},"error":{"type":"null"}}}}}},"400":{"description":"limit out of range","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"403":{"description":"Delegated access token without billing:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/orders/{id}":{"get":{"summary":"Get one order by its Digistore24 order id","operationId":"getOrder","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","maxLength":200}}],"responses":{"200":{"description":"The order","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Order"},"error":{"type":"null"}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"403":{"description":"Delegated access token without billing:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"No such order for this account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/billing":{"get":{"summary":"Usage, message quota and credit balance of the account","operationId":"getBilling","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Usage"},"error":{"type":"null"}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"403":{"description":"Delegated access token without billing:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/subscription":{"get":{"summary":"Subscription status of the account (read-only; changing or cancelling the plan is not available via this API)","operationId":"getSubscription","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Subscription"},"error":{"type":"null"}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"403":{"description":"Delegated access token without billing:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/team":{"get":{"summary":"Team members, pending invitations and seats","operationId":"getTeam","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Team"},"error":{"type":"null"}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"403":{"description":"Delegated access token without account:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/account":{"get":{"summary":"Company details of the account (read-only)","operationId":"getAccount","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Account"},"error":{"type":"null"}}}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"403":{"description":"Delegated access token without account:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/handover-requests":{"get":{"summary":"List handover requests for the authenticated user","operationId":"listHandoverRequests","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["requested","notified","accepted","resolved","cancelled"]}},{"name":"dateFrom","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"maximum":200}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Array of handover requests"},"400":{"description":"Invalid status filter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/handover-requests/{id}":{"get":{"summary":"Get handover request by ID","operationId":"getHandoverRequest","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"HandoverRequest object"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Handover request not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"summary":"Accept, resolve, or cancel a handover request","operationId":"updateHandoverRequest","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"type":"string","enum":["accept","resolve","cancel"]},"assignedToUserId":{"type":"string","description":"Nur für action=accept: welcher Mitarbeiter übernimmt"},"resolutionNotes":{"type":"string","description":"Nur für action=resolve: Abschlussnotiz"}}}}}},"responses":{"200":{"description":"Updated handover request"},"400":{"description":"Invalid action","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Handover request not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/handover-settings/{chatbotId}":{"get":{"summary":"Get handover settings for a chatbot","operationId":"getHandoverSettings","parameters":[{"name":"chatbotId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"HandoverSettings object or null"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"put":{"summary":"Create or update handover settings for a chatbot","operationId":"upsertHandoverSettings","parameters":[{"name":"chatbotId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean"},"notificationEmail":{"type":"string","nullable":true},"slackWebhookUrl":{"type":"string","nullable":true},"businessHours":{"type":"object","description":"Keys: mo/di/mi/do/fr/sa/so → [startHour, endHour] oder null"},"outsideHoursMessage":{"type":"string"},"autoHandoverKeywords":{"type":"array","items":{"type":"string","pattern":"\\S"},"description":"Each keyword must contain at least one non-whitespace character; an empty or blank keyword is rejected with 400."}}}}}},"responses":{"200":{"description":"Upserted HandoverSettings"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Chatbot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/api/v1/proactive-triggers":{"get":{"summary":"List proactive triggers for the authenticated user","operationId":"listProactiveTriggers","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":200,"maximum":200}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0}}],"responses":{"200":{"description":"Array of ProactiveTrigger objects"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"summary":"Create a proactive trigger","operationId":"createProactiveTrigger","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chatbotId","name","triggerType"],"properties":{"chatbotId":{"type":"string"},"name":{"type":"string"},"triggerType":{"type":"string","enum":["time_on_page","exit_intent","scroll_depth","page_view_count","inactivity"]},"conditionValue":{"type":"object","description":"{ seconds } | { percent } | { count } | {}"},"targetPagePattern":{"type":"string","default":"*"},"messageTemplate":{"type":"string"},"cooldownMinutes":{"type":"integer","default":60},"enabled":{"type":"boolean","default":true},"priority":{"type":"integer","default":0}}}}}},"responses":{"201":{"description":"Created ProactiveTrigger"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"409":{"$ref":"#/components/responses/IdempotencyInProgress"},"422":{"$ref":"#/components/responses/IdempotencyMismatch"},"429":{"$ref":"#/components/responses/RateLimited"}},"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}]}},"/api/v1/proactive-triggers/{id}":{"get":{"summary":"Get a proactive trigger by ID","operationId":"getProactiveTrigger","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"ProactiveTrigger object"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Trigger not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"summary":"Partially update a proactive trigger","operationId":"updateProactiveTrigger","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"triggerType":{"type":"string","enum":["time_on_page","exit_intent","scroll_depth","page_view_count","inactivity"]},"conditionValue":{"type":"object"},"targetPagePattern":{"type":"string"},"messageTemplate":{"type":"string"},"cooldownMinutes":{"type":"integer"},"enabled":{"type":"boolean"},"priority":{"type":"integer"}}}}}},"responses":{"200":{"description":"Updated ProactiveTrigger"},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Trigger not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"summary":"Delete a proactive trigger","operationId":"deleteProactiveTrigger","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deletion confirmed"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"404":{"description":"Trigger not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Error"}}}},"429":{"$ref":"#/components/responses/RateLimited"}}}}},"webhooks":{"lead.created":{"post":{"summary":"A chatbot captured a lead: a contact request, an appointment booking or a callback request. The event names the lead; read its contents with the leads endpoint of the chatbot.","x-event-version":"1.0","x-feed-path":"/api/v1/events?type=lead.created","description":"Sent as POST to the account webhook URL and to chatbot webhooks. Headers: X-Smartwebchat-Event, X-Smartwebchat-Timestamp, X-Smartwebchat-Signature (HMAC over timestamp and body). For backward compatibility, data carries the full lead object under data.lead (the example is shortened); the feed carries only leadId.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["event","timestamp","data"],"properties":{"event":{"type":"string","const":"lead.created"},"timestamp":{"type":"string","format":"date-time"},"data":{"type":"object","description":"For backward compatibility, data carries the full lead object under data.lead (the example is shortened); the feed carries only leadId."}}},"example":{"event":"lead.created","timestamp":"2026-09-24T12:00:00.000Z","data":{"lead":{"id":"lead_2f9c1e","chatbotId":"bot_1","name":"…","email":"…","phone":null,"message":"…","status":"new","createdAt":"2026-09-24T11:59:00.000Z"}}}}}},"responses":{"2XX":{"description":"Received. Any other status is logged; delivery to chatbot webhooks is retried, delivery to the account webhook URL is not."}}}},"handover.requested":{"post":{"summary":"A visitor asked for a person, or the chatbot handed the conversation over. The event names the request; read it with the handover requests endpoint.","x-event-version":"1.0","x-feed-path":"/api/v1/events?type=handover.requested","description":"Sent as POST to the account webhook URL. Headers: X-Smartwebchat-Event, X-Smartwebchat-Timestamp, X-Smartwebchat-Signature (HMAC over timestamp and body). For backward compatibility, data carries the full request under data.handoverRequest (the example is shortened); the feed carries only handoverRequestId.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["event","timestamp","data"],"properties":{"event":{"type":"string","const":"handover.requested"},"timestamp":{"type":"string","format":"date-time"},"data":{"type":"object","description":"For backward compatibility, data carries the full request under data.handoverRequest (the example is shortened); the feed carries only handoverRequestId."}}},"example":{"event":"handover.requested","timestamp":"2026-09-24T12:00:00.000Z","data":{"handoverRequest":{"id":"ho_7a1b2c","chatbotId":"bot_1","status":"requested","createdAt":"2026-09-24T11:59:30.000Z"}}}}}},"responses":{"2XX":{"description":"Received. Any other status is logged; delivery to the account webhook URL is not retried."}}}},"quota.threshold":{"post":{"summary":"The account used a warning share of its monthly credit. Sent once per threshold and billing month. A person tops up the credit or changes the plan in the dashboard. In the feed it may disappear and reappear with the same id if the warning mail failed; deduplicate by id.","x-event-version":"1.0","x-feed-path":"/api/v1/events?type=quota.threshold","description":"Sent as POST to the account webhook URL. Headers: X-Smartwebchat-Event, X-Smartwebchat-Timestamp, X-Smartwebchat-Signature (HMAC over timestamp and body). data is the object shown in the example.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["event","timestamp","data"],"properties":{"event":{"type":"string","const":"quota.threshold"},"timestamp":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"thresholdPercent":{"type":"integer","minimum":1,"maximum":100},"period":{"type":"string"}},"required":["thresholdPercent","period"],"additionalProperties":false}}},"example":{"event":"quota.threshold","timestamp":"2026-09-24T12:00:00.000Z","data":{"thresholdPercent":80,"period":"2026-09"}}}}},"responses":{"2XX":{"description":"Received. Any other status is logged; delivery to the account webhook URL is not retried."}}}},"payment.failed":{"post":{"summary":"The payment provider reported a missed recurring payment. Access is not withdrawn by this event. A person updates the payment method with the payment provider. Repeated notifications for the same payment transaction within a short retry window are delivered once; a later failure of the same transaction is a new event. Without a transaction id a notification may be delivered more than once, then with different ids.","x-event-version":"1.0","x-feed-path":"/api/v1/events?type=payment.failed","description":"Sent as POST to the account webhook URL. Headers: X-Smartwebchat-Event, X-Smartwebchat-Timestamp, X-Smartwebchat-Signature (HMAC over timestamp and body). data is the object shown in the example.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["event","timestamp","data"],"properties":{"event":{"type":"string","const":"payment.failed"},"timestamp":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{},"additionalProperties":false}}},"example":{"event":"payment.failed","timestamp":"2026-09-24T12:00:00.000Z","data":{}}}}},"responses":{"2XX":{"description":"Received. Any other status is logged; delivery to the account webhook URL is not retried."}}}},"job.completed":{"post":{"summary":"A knowledge job finished: a website crawl or the processing of a knowledge source. Sent once per run; reading the same source again is a new run with a new event. Pages of a crawl are reported with the crawl.","x-event-version":"1.0","x-feed-path":"/api/v1/events?type=job.completed","description":"Sent as POST to the account webhook URL. Headers: X-Smartwebchat-Event, X-Smartwebchat-Timestamp, X-Smartwebchat-Signature (HMAC over timestamp and body). data is the object shown in the example.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["event","timestamp","data"],"properties":{"event":{"type":"string","const":"job.completed"},"timestamp":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"jobId":{"type":"string"},"jobType":{"type":"string","enum":["knowledge_crawl","knowledge_source"]},"status":{"type":"string","enum":["succeeded","partially_succeeded"]},"errorCode":{"type":"null"}},"required":["jobId","jobType","status","errorCode"],"additionalProperties":false}}},"example":{"event":"job.completed","timestamp":"2026-09-24T12:00:00.000Z","data":{"jobId":"crawl_2f9c1e7a-0000-4000-8000-000000000000","jobType":"knowledge_crawl","status":"succeeded","errorCode":null}}}}},"responses":{"2XX":{"description":"Received. Any other status is logged; delivery to the account webhook URL is not retried."}}}},"job.failed":{"post":{"summary":"A knowledge job failed for good, after its retries. errorCode is a code from the error catalog. Sent once per run; a retry that later succeeds sends no failure.","x-event-version":"1.0","x-feed-path":"/api/v1/events?type=job.failed","description":"Sent as POST to the account webhook URL. Headers: X-Smartwebchat-Event, X-Smartwebchat-Timestamp, X-Smartwebchat-Signature (HMAC over timestamp and body). data is the object shown in the example.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["event","timestamp","data"],"properties":{"event":{"type":"string","const":"job.failed"},"timestamp":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"jobId":{"type":"string"},"jobType":{"type":"string","enum":["knowledge_crawl","knowledge_source"]},"status":{"type":"string","const":"failed"},"errorCode":{"type":"string"}},"required":["jobId","jobType","status","errorCode"],"additionalProperties":false}}},"example":{"event":"job.failed","timestamp":"2026-09-24T12:00:00.000Z","data":{"jobId":"source_7a1b2c3d-0000-4000-8000-000000000000","jobType":"knowledge_source","status":"failed","errorCode":"no_extractable_text"}}}}},"responses":{"2XX":{"description":"Received. Any other status is logged; delivery to the account webhook URL is not retried."}}}}}}