Get started
Website forms
Put a Kweko form on any website with one script tag, or post to the public form endpoint from your own form. Every submission becomes a lead with its UTM tags, without duplicate clients.
Embed with widget.js
Owners and admins build forms in Settings → Website forms. Each form has a public id (f…) and the page shows ready snippets:
<script src="https://your-workspace.kweko.uz/widget.js" data-kweko-form="fx7q2m…" async></script>data-mode="popup"shows a button (data-button="Leave a request", ordata-button="none") and opens the form in a dialog. Any link to#kweko-<form id>, any element withdata-kweko-open="<form id>"andKweko.open("<form id>")open it too.data-target="#contact"renders an inline form into that element.data-lang="uz|ru|en"overrides the visitor's browser language;data-theme="dark|auto"switches colours.- The same script runs the web chat bubble:
data-kweko-chat="<channel id>". - After a submission the page receives the
kweko:form-submittedwindow event (event.detail.form).
The script is about 12 KB gzipped, renders in a closed Shadow DOM, uses no eval and no HTML strings, and never sends cookies. On a site with a Content-Security-Policy, allow your workspace address in script-src and connect-src. /widget.js is cached for five minutes (so fixes reach every site); /widget.js?v=<version> is immutable.
Forms also have a hosted page at https://your-workspace.kweko.uz/f/<form id> once the workspace is verified.
Post from your own form
The widget calls two public endpoints on your workspace address. They take no API key and no cookies; call them from the visitor's browser.
curl "https://your-workspace.kweko.uz/api/forms/fx7q2m…?lang=ru"{ "id": "fx7q2m…", "lang": "ru", "title": "Оставьте заявку", "submit": "Отправить", "consent": "",
"fields": [{ "id": "name", "type": "text", "label": "Имя", "required": true, "autocomplete": "name" },
{ "id": "phone", "type": "phone", "label": "Телефон", "required": true, "autocomplete": "tel" }],
"color": "#c9420b", "token": "lx3k9a.Qm…", "min_ms": 3000 }curl https://your-workspace.kweko.uz/api/forms/fx7q2m…/submit \
-H "Content-Type: application/json" \
-d '{"token": "lx3k9a.Qm…", "answers": {"name": "Dilnoza", "phone": "90 123 45 67"},
"utm": {"utm_source": "instagram"}, "referrer": "https://instagram.com/", "landing_page": "https://shop.uz/sale", "lang": "ru"}'{ "ok": true, "success": "Спасибо! Мы скоро свяжемся с вами.", "redirect_url": "" }tokencomes from the config call. It proves when the form was loaded: submissions sent less thanmin_msafter loading, or with the hiddenwebsitefield filled in, get the same201but are dropped. A missing, forged or day-old token returns409 form_expired; load the config again.answersare keyed by field id. Phones are normalized to+998…like everywhere in Kweko. Field errors come back as422 validation_failedwithfieldskeyed by field id, in the visitor's language (X-Kweko-Locale).consent: trueis required when the form has a consent text.
What a submission does
Kweko looks for the client by phone, then by email. A known client is reused; depending on the form, the submission is added to their open lead or opens a new one. A new lead lands in the form's pipeline and stage with its source webform, tags, owner rule, custom field answers, utm, referrer and landing_page (lead fields). The lead's timeline shows the answers.
Events: form.submitted for every submission, plus the usual lead.created and contact.created when records are new, so automations and webhooks see form leads like any other.
Protection and limits
| Limit | Value |
|---|---|
| Submissions per visitor IP | 10 per minute |
| Submissions per form | 2,000 per day, at most 60 in a burst |
| Request body | 32 KB, 40 answers, 5,000 characters per answer |
| Forms per workspace, submissions per month | By plan (see Usage in Settings) |
Over a rate limit the endpoint answers 429 rate_limited with Retry-After; over the plan's monthly submissions it answers 429 form_quota_reached (the admins are notified). Card numbers are refused. With allowed websites set on a form, only those origins (exact, or https://*.example.uz for subdomains) and your hosted page may load and submit it (403 origin_not_allowed); CORS never allows credentials. Paused or deleted forms return 404 form_unavailable.