Kommo + GetResponse: email automation and webinars from the sales pipeline

GetResponse is a Polish email marketing and webinar platform with EU hosting: email automation, landing pages, webinars (up to 1,000 attendees), push notifications. Popular in the EU as a GDPR-compliant alternative to Mailchimp. Unlike Klaviyo or Drip, GetResponse includes a webinar module in the base plan — important for B2B companies with webinar-based sales. Without Kommo integration, email contacts and CRM deals live separately. With integration, Won -> contact in the right GetResponse segment automatically.

GetResponse vs Mailchimp vs Brevo for EU teams

ParameterGetResponseMailchimpBrevo
WebinarsYes, native (up to 500 or 1000)NoNo
EU hostingYes (Poland)USFrance
GDPR complianceYes, built-inPartialYes
AutomationVisual builderBasicGood
Price (1,000 contacts)$19/mo$26/mo$25/mo
APIREST v3, API KeyREST, API KeyREST, API Key

GetResponse is chosen by EU companies with a webinar strategy and strict GDPR data storage requirements.

What gets synchronized

Kommo -> GetResponse:
— Won -> create/update Contact with tags customer, plan_{tier}, source_{channel}
— Won -> add to “Paying Customers” list
— Plan change -> update tag
— Client churned -> tag churned, remove from “Paying Customers”

GetResponse -> Kommo:
— Webinar registration -> create lead in Kommo (name, email, webinar)
subscriber.unsubscribed -> Note + task for manager
— Email click on a key link -> Note in deal (optional)

GetResponse API: key requests

Base URL: https://api.getresponse.com/v3.
Authentication: X-Auth-Token: api-key {api_key}.
API Key: GetResponse -> Account Settings -> Integrations -> API.

import requests
from datetime import datetime, timezone

GR_API_KEY = "your_api_key"
GR_BASE_URL = "https://api.getresponse.com/v3"
HEADERS = {
    "X-Auth-Token": f"api-key {GR_API_KEY}",
    "Content-Type": "application/json",
}

def upsert_contact(email: str, name: str, campaign_id: str,
                   tags: list, custom_fields: dict = None) -> dict:
    # GetResponse has no true upsert - use GET+POST or UPDATE
    existing = get_contact_by_email(email)
    if existing:
        return update_contact(existing["contactId"], tags, custom_fields or {})
    return create_contact(email, name, campaign_id, tags, custom_fields or {})

def get_contact_by_email(email: str) -> dict | None:
    resp = requests.get(
        f"{GR_BASE_URL}/contacts",
        headers=HEADERS,
        params={"query[email]": email},
    )
    resp.raise_for_status()
    contacts = resp.json()
    return contacts[0] if contacts else None

def create_contact(email: str, name: str, campaign_id: str,
                   tags: list, custom_fields: dict) -> dict:
    payload = {
        "email": email,
        "name": name,
        "campaign": {"campaignId": campaign_id},
        "tags": [{"name": t} for t in tags],
    }
    if custom_fields:
        payload["customFieldValues"] = [
            {"customFieldId": k, "value": [v]}
            for k, v in custom_fields.items()
        ]
    resp = requests.post(
        f"{GR_BASE_URL}/contacts",
        headers=HEADERS, json=payload,
    )
    if resp.status_code == 202:
        return {"status": "queued"}
    resp.raise_for_status()
    return resp.json()

def update_contact(contact_id: str, tags: list, custom_fields: dict) -> dict:
    payload = {"tags": [{"name": t} for t in tags]}
    if custom_fields:
        payload["customFieldValues"] = [
            {"customFieldId": k, "value": [v]}
            for k, v in custom_fields.items()
        ]
    resp = requests.post(
        f"{GR_BASE_URL}/contacts/{contact_id}",
        headers=HEADERS, json=payload,
    )
    resp.raise_for_status()
    return resp.json()

GR_CAMPAIGN_ID = "your_campaign_id"  # from GetResponse Contacts -> Lists -> ID

def on_deal_won(lead: dict, contact: dict):
    email = get_contact_email(contact)
    name = contact["name"]
    plan = get_custom_field(lead, PLAN_FIELD_ID) or "starter"
    source = get_custom_field(lead, SOURCE_FIELD_ID) or "direct"
    amount = lead.get("price", 0)

    tags = ["customer", f"plan_{plan}", f"source_{source}", "active"]

    custom_fields = {
        GR_FIELD_PLAN:    plan,
        GR_FIELD_MRR:     str(amount),
        GR_FIELD_DEAL_ID: str(lead["id"]),
        GR_FIELD_WON_DATE: datetime.now(timezone.utc).strftime("%Y-%m-%d"),
    }

    upsert_contact(email, name, GR_CAMPAIGN_ID, tags, custom_fields)
    create_kommo_note(lead["id"],
        f"GetResponse: contact added (tags: customer, plan_{plan})")

def on_webinar_registration(webinar_id: str, contact_data: dict):
    # GetResponse webhook on webinar registration
    email = contact_data.get("email", "")
    name  = contact_data.get("name", "")
    webinar_name = contact_data.get("webinar_name", webinar_id)

    # Create lead in Kommo
    create_kommo_lead(
        title=f"Webinar: {webinar_name} - {name}",
        contact_email=email,
        contact_name=name,
        tags=["webinar-lead", f"webinar_{webinar_id}"],
    )

GetResponse Webhook (subscribe/unsubscribe):

@app.route("/webhooks/getresponse", methods=["POST"])
def gr_webhook():
    payload = request.json
    action  = payload.get("action")
    contact = payload.get("contact", {})
    email   = contact.get("email", "")

    if not email:
        return "", 200

    deal_id = find_kommo_deal_by_contact_email(email)

    if action == "subscribe" and payload.get("origin") == "webinar":
        webinar = payload.get("webinar", {})
        on_webinar_registration(webinar.get("id", ""), {
            "email": email,
            "name": contact.get("name", ""),
            "webinar_name": webinar.get("name", ""),
        })

    elif action == "unsubscribe" and deal_id:
        create_kommo_note(deal_id, "GetResponse: client unsubscribed from mailing list")
        create_kommo_task(deal_id,
            "Clarify preferences - client unsubscribed from GetResponse")

    return "", 200

Webinar flow: GetResponse as a lead magnet

For B2B companies with a webinar strategy, the integration works in both directions:

From GetResponse to Kommo (lead generation):
— Webinar registration -> lead in Kommo with tag webinar-{name}
— Webinar attendance -> update lead status (via GetResponse API: attended vs registered list)
— Webinar chat question -> Note in lead (if integrated via GetResponse API)

From Kommo to GetResponse (lead nurturing):
— Webinar lead did not buy -> enters GetResponse nurture sequence
— After Won -> moved to post-purchase sequence

Real-world case

B2B consulting (Poland + EU, 200 email subscribers + 4 webinars per quarter, Kommo + GetResponse):

  • Before: webinar leads were manually copied from GetResponse to Kommo (Excel export -> import). Delay 1–3 days. 20% of leads were lost. Paying clients received nurture emails as if they had not purchased.
  • After: webinar registration -> lead in Kommo within a minute. Won -> customer tag in GetResponse -> client is excluded from prospect sequences and enters the onboarding sequence. 0 lost leads, 0 “sales” emails to paying clients.

Who this is relevant for

  • EU companies with GDPR requirements for email marketing (GetResponse EU hosting)
  • B2B companies with a webinar acquisition strategy: registrations -> CRM leads automatically
  • SaaS with tiered plans: different email sequences for each plan
  • Companies already on GetResponse who want to connect it to Kommo

Frequently asked questions

GetResponse creates a contact with a delay (202 Accepted) — how to handle this?

The GetResponse API returns 202 when creating a contact — this is an asynchronous operation, the contact is created in a queue. There is no immediate ID. For subsequent operations (update, tag) — you need to GET by email after a few seconds. In production: save email as the key and retry after 5–10 seconds if GET returned an empty array.

How do I get the list of webinar attendees (attended) vs only registered?

GET /webinars/{webinar_id}/attendees — list of confirmed attendees. GET /webinars/{webinar_id}/registrants — all registered. The difference allows building two different scenarios in Kommo: no-show -> follow-up task; attended -> high-priority lead.

Does GetResponse support double opt-in when creating via API?

Yes. Parameter dayOfCycle: 0 in the request body when creating a contact. GetResponse will send a confirmation email. After confirmation, the status changes to subscribed. For EU teams with GDPR, double opt-in must be specified when creating via API.

How do you authenticate a GetResponse webhook?

GetResponse uses a shared secret in the URL or IP verification. Recommended: secret path (/webhooks/getresponse/{token}) + IP whitelist. GetResponse publishes its IP list in the documentation.

Summary

  • GetResponse API: X-Auth-Token: api-key {key}, https://api.getresponse.com/v3
  • Create contact: POST -> 202 Accepted (async), retry needed for subsequent operations
  • Upsert: GET by email -> if exists: PATCH, if not: POST
  • Webhook: subscribe, unsubscribe, webinar events
  • Webinar flow: registration -> lead in Kommo; Won -> contact in GetResponse with correct tags
  • EU hosting: data in Poland, GDPR double opt-in via API

If you use GetResponse and Kommo and want to synchronize CRM statuses with email segments — describe your list structure and webinar process. Exceltic.dev will configure the two-way integration.

More articles

All →