Qwilr is a platform for creating sales proposals in the format of interactive web pages. Instead of PDF — a live page with video, ROI calculators, built-in electronic signature, and analytics: who opened it, how long they spent, and which sections they read. Unlike PandaDoc or GetAccept, Qwilr builds a web experience rather than an electronic document. Without Kommo integration, a manager creates proposals manually. With the integration, Won -> proposal with deal data is sent to the client in 30 seconds.
Qwilr vs PandaDoc vs GetAccept: Proposal Formats
| Parameter | Qwilr | PandaDoc | GetAccept |
|---|---|---|---|
| Format | Web page (URL) | PDF + rich content | PDF + video |
| View analytics | Detailed (section-level) | Basic | Available |
| ROI calculators | Built-in, interactive | No | No |
| E-sign | Yes | Yes | Yes |
| Branding | Full | Full | Partial |
| Best for | B2B SaaS, agencies | Any | Sales + video pitches |
Qwilr wins when the product or service requires explanation: interactive pricing calculator, video demo inside the proposal, content adaptable to client segment.
What Gets Synchronised
Kommo -> Qwilr: — Won -> create Document from template with data (name, company, amount, plan) — Save proposal URL in Note and deal field
Qwilr -> Kommo:
— proposal.viewed -> Note: “Qwilr: client opened the proposal (X min)”
— proposal.accepted (signed) -> Note + stage change to “Proposal Accepted”
— proposal.declined -> Note + task: “Client declined — clarify objections”
— proposal.expired -> Note + task: “Proposal expired — resend”
Qwilr API: Key Requests
Base URL: https://api.qwilr.com/v1.
Authentication: Authorization: Bearer {api_key}.
API Key: Qwilr -> Settings -> Integrations -> API.
import requests
QWILR_API_KEY = "your_api_key"
QWILR_BASE_URL = "https://api.qwilr.com/v1"
HEADERS = {
"Authorization": f"Bearer {QWILR_API_KEY}",
"Content-Type": "application/json",
}
def list_templates() -> list:
# Get list of templates to select the right one
resp = requests.get(f"{QWILR_BASE_URL}/templates", headers=HEADERS)
resp.raise_for_status()
return resp.json().get("data", [])
def create_document(template_id: str, name: str, tokens: dict) -> dict:
# tokens - template variables: {ClientName}, {CompanyName}, {Price}, etc.
payload = {
"template_id": template_id,
"name": name,
"tokens": tokens,
}
resp = requests.post(
f"{QWILR_BASE_URL}/documents",
headers=HEADERS,
json=payload,
)
resp.raise_for_status()
return resp.json()
def get_document(document_id: str) -> dict:
resp = requests.get(
f"{QWILR_BASE_URL}/documents/{document_id}",
headers=HEADERS,
)
resp.raise_for_status()
return resp.json()
def on_deal_won(lead: dict, contact: dict):
name = contact["name"]
email = get_contact_email(contact)
company = get_custom_field(lead, COMPANY_FIELD_ID) or name
plan = get_custom_field(lead, PLAN_FIELD_ID) or "Growth"
amount = lead.get("price", 0)
tokens = {
"ClientName": name,
"CompanyName": company,
"ClientEmail": email,
"PlanName": plan,
"Price": f"${amount:,.0f}",
"DealId": str(lead["id"]),
}
doc = create_document(
template_id=QWILR_TEMPLATE_ID,
name=f"Proposal for {company}",
tokens=tokens,
)
doc_id = doc["id"]
view_url = doc.get("view_url", "")
update_kommo_deal(lead["id"], {"qwilr_document_id": doc_id})
create_kommo_note(lead["id"],
f"Qwilr: proposal created\nClient link: {view_url}")
Handling Qwilr Webhook:
@app.route("/webhooks/qwilr", methods=["POST"])
def qwilr_webhook():
payload = request.json
event = payload.get("event")
doc_id = str(payload.get("document", {}).get("id", ""))
deal_id = find_deal_by_field("qwilr_document_id", doc_id)
if not deal_id:
return "", 200
if event == "proposal.viewed":
duration = payload.get("metadata", {}).get("duration_seconds", 0)
mins = duration // 60
create_kommo_note(deal_id,
f"Qwilr: client opened the proposal ({mins} min)")
elif event == "proposal.accepted":
signer = payload.get("signer", {}).get("name", "")
update_kommo_deal(deal_id, {"stage_id": STAGE_PROPOSAL_ACCEPTED})
create_kommo_note(deal_id,
f"Qwilr: proposal accepted and signed ({signer})")
elif event == "proposal.declined":
reason = payload.get("metadata", {}).get("reason", "")
create_kommo_note(deal_id,
f"Qwilr: client declined the proposal. Reason: {reason}")
create_kommo_task(deal_id,
"Clarify objections - client declined the Qwilr proposal")
return "", 200
View Tracking: Why It Matters for Sales
Qwilr shows: who opened it, when, and how long they spent on each section. Through the Kommo integration, this appears in the deal card. Practical scenarios:
- Client opened the proposal and spent 12 minutes on the Pricing section -> Note in Kommo -> manager sees this and calls with a specific price offer
- Client opened it, stayed 30 seconds -> Note -> manager understands the proposal was not read and reformats it
Without the integration, this data stays in Qwilr and managers never see it.
Real-World Case
Digital agency (UK, 30–40 proposals per month, Kommo + Qwilr):
- Before: PandaDoc, PDF, 20–30 minutes to create a proposal manually. No view analytics. The manager did not know whether the client had looked at it.
- After: Won -> Qwilr from template in 60 seconds.
proposal.viewed-> Note -> manager calls 30 minutes after viewing. Proposal conversion: 34% (was 21%). Time to close shortened from 18 to 11 days. - Additionally: ROI calculator in the proposal — the client enters their own data and sees their own outcome. The manager can see in tracking how long they spent on the calculator.
Who This Is Relevant For
- Agencies and consultancies with 10+ proposals per month
- SaaS with enterprise sales: proposals requiring ROI justification
- Companies where PDF proposals regularly “get lost” in the client’s inbox
- Teams where the manager does not know “did the client look at our proposal”
Frequently Asked Questions
Qwilr vs PandaDoc — when to choose which?
PandaDoc: PDF format is required (legal documents, enterprise with paper trail requirements), forms for data collection inside the document are needed. Qwilr: maximum visual impact, interactive calculators, video inside, detailed tracking. For agencies with modern clients — Qwilr looks significantly more professional.
Qwilr tokens — how do I find out which variables the template supports?
Via GET /templates/{id} — the response contains a tokens array with variable names. Or in the Qwilr editor: { -> list of available variables. Variables can be added directly in the editor before the name using double curly braces.
Does Qwilr support legally binding electronic signatures?
Yes, Qwilr e-sign is a Simple Electronic Signature, legally valid in most jurisdictions (equivalent to DocuSign SES). For a Qualified Electronic Signature (QES, mandatory in some EU contracts) — a separate tool such as Docuseal or Oneflow with a QES provider is needed.
Can the Qwilr link be sent to the client directly from Kommo?
Not natively, but through the integration: after document creation, view_url is saved in a Note and custom field. The manager copies the link from the field and sends it via WhatsApp or email directly from Kommo. Automated sending via Kommo SendGrid or email integration — the next automation step.
Summary
- Qwilr API:
Authorization: Bearer {api_key},https://api.qwilr.com/v1 - Create document:
POST /documentswith template_id and tokens - Webhook:
proposal.viewed,proposal.accepted,proposal.declined - View tracking -> Note in Kommo -> manager knows when to call
- Web page format instead of PDF — higher engagement, detailed analytics
If you use Qwilr and Kommo and want to automate proposal creation on Won — describe your template structure and variables. Exceltic.dev will configure the integration with view tracking.