From f4e46cdfd8e823ba9f58f8c92ee577192ef0d250 Mon Sep 17 00:00:00 2001 From: Denys Davydov Date: Wed, 8 Jun 2022 12:43:26 +0300 Subject: [PATCH] #259 on call: Source Hubspot - fix for the property_history stream which did not emit any records --- .../connectors/source-hubspot/Dockerfile | 2 +- .../source-hubspot/acceptance-test-config.yml | 96 ++------- .../integration_tests/abnormal_state.json | 3 + .../integration_tests/expected_records.txt | 148 ++++++++++++++ .../sample_files/basic_read_catalog.json | 166 ++++++++++++++++ ...fig.json => basic_read_oauth_catalog.json} | 0 .../sample_files/full_refresh_catalog.json | 9 - .../full_refresh_oauth_catalog.json | 184 ++++++++++++++++++ ..._catalog.json => incremental_catalog.json} | 2 +- .../source-hubspot/source_hubspot/helpers.py | 47 +++++ .../schemas/property_history.json | 3 +- .../source-hubspot/source_hubspot/streams.py | 71 ++++--- .../source-hubspot/unit_tests/test_source.py | 9 +- docs/integrations/sources/hubspot.md | 1 + 14 files changed, 619 insertions(+), 122 deletions(-) create mode 100644 airbyte-integrations/connectors/source-hubspot/integration_tests/expected_records.txt create mode 100644 airbyte-integrations/connectors/source-hubspot/sample_files/basic_read_catalog.json rename airbyte-integrations/connectors/source-hubspot/sample_files/{configured_catalog_for_oauth_config.json => basic_read_oauth_catalog.json} (100%) create mode 100644 airbyte-integrations/connectors/source-hubspot/sample_files/full_refresh_oauth_catalog.json rename airbyte-integrations/connectors/source-hubspot/sample_files/{configured_catalog.json => incremental_catalog.json} (99%) create mode 100644 airbyte-integrations/connectors/source-hubspot/source_hubspot/helpers.py diff --git a/airbyte-integrations/connectors/source-hubspot/Dockerfile b/airbyte-integrations/connectors/source-hubspot/Dockerfile index 34fb7c7b50c1e..24e672d10327d 100644 --- a/airbyte-integrations/connectors/source-hubspot/Dockerfile +++ b/airbyte-integrations/connectors/source-hubspot/Dockerfile @@ -34,5 +34,5 @@ COPY source_hubspot ./source_hubspot ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py" ENTRYPOINT ["python", "/airbyte/integration_code/main.py"] -LABEL io.airbyte.version=0.1.66 +LABEL io.airbyte.version=0.1.67 LABEL io.airbyte.name=airbyte/source-hubspot diff --git a/airbyte-integrations/connectors/source-hubspot/acceptance-test-config.yml b/airbyte-integrations/connectors/source-hubspot/acceptance-test-config.yml index 6fe0511464495..5be369de136d6 100644 --- a/airbyte-integrations/connectors/source-hubspot/acceptance-test-config.yml +++ b/airbyte-integrations/connectors/source-hubspot/acceptance-test-config.yml @@ -18,88 +18,32 @@ tests: basic_read: - config_path: "secrets/config.json" timeout_seconds: 600 - configured_catalog_path: "sample_files/full_refresh_catalog.json" - empty_streams: ["workflows", "form_submissions", "ticket_pipelines", "property_history"] + configured_catalog_path: "sample_files/basic_read_catalog.json" + empty_streams: ["workflows", "form_submissions", "ticket_pipelines"] + expect_records: + path: "integration_tests/expected_records.txt" - config_path: "secrets/config_oauth.json" timeout_seconds: 600 - configured_catalog_path: "sample_files/configured_catalog_for_oauth_config.json" - # The `campaigns` stream is empty in this case, because we use a catalog with - # incremental streams: subscription_changes and email_events (it takes a long time to read) - # and therefore the start date is set at 2021-10-10 for `config_oauth.json`, - # but the campaign was created on 2021-01-11 - empty_streams: ["campaigns", "workflows", "contacts_list_memberships", "form_submissions", "ticket_pipelines", "property_history"] + configured_catalog_path: "sample_files/basic_read_oauth_catalog.json" + empty_streams: ["workflows", "contacts_list_memberships", "form_submissions", "ticket_pipelines"] + expect_records: + path: "integration_tests/expected_records.txt" incremental: - config_path: "secrets/config.json" - configured_catalog_path: "sample_files/configured_catalog.json" + configured_catalog_path: "sample_files/incremental_catalog.json" future_state_path: "integration_tests/abnormal_state.json" full_refresh: - config_path: "secrets/config.json" + # This config is the same as for basic read except for missing `property_history` stream. + # This stream emits records with dynamic timestamps under some conditions + # (properties like `hs_time_in_lead`, `hs_time_in_subscriber` etc.) which makes it impossible to compare records. + # Ignoring these fields makes testing this stream senseless because those valuable values of other property types + # will also be ignored. Instead, we test this stream against expected records in basic read test. configured_catalog_path: "sample_files/full_refresh_catalog.json" - ignored_fields: - "companies": ["properties", "hs_time_in_customer"] - "companies": ["properties", "hs_time_in_evangelist"] - "companies": ["properties", "hs_time_in_lead"] - "companies": ["properties", "hs_time_in_marketingqualifiedlead"] - "companies": ["properties", "hs_time_in_opportunity"] - "companies": ["properties", "hs_time_in_other"] - "companies": ["properties", "hs_time_in_salesqualifiedlead"] - "companies": ["properties", "hs_time_in_subscriber"] - "contacts": ["properties", "hs_time_in_customer"] - "contacts": ["properties", "hs_time_in_evangelist"] - "contacts": ["properties", "hs_time_in_lead"] - "contacts": ["properties", "hs_time_in_marketingqualifiedlead"] - "contacts": ["properties", "hs_time_in_opportunity"] - "contacts": ["properties", "hs_time_in_other"] - "contacts": ["properties", "hs_time_in_salesqualifiedlead"] - "contacts": ["properties", "hs_time_in_subscriber"] - "deals": ["properties", "hs_time_in_9567448"] - "deals": ["properties", "hs_time_in_9567449"] - "deals": ["properties", "hs_time_in_appointmentscheduled"] - "deals": ["properties", "hs_time_in_closedlost"] - "deals": ["properties", "hs_time_in_closedwon"] - "deals": ["properties", "hs_time_in_contractsent"] - "deals": ["properties", "hs_time_in_customclosedwonstage"] - "deals": ["properties", "hs_time_in_decisionmakerboughtin"] - "deals": ["properties", "hs_time_in_presentationscheduled"] - "deals": ["properties", "hs_time_in_qualifiedtobuy"] - "tickets": ["properties", "hs_time_in_1"] - "tickets": ["properties", "hs_time_in_2"] - "tickets": ["properties", "hs_time_in_3"] - "tickets": ["properties", "hs_time_in_4"] - "property_history": ["property", "hs_time_in_lead"] - "property_history": ["property", "hs_time_in_subscriber"] - config_path: "secrets/config_oauth.json" - configured_catalog_path: "sample_files/configured_catalog_for_oauth_config.json" - ignored_fields: - "companies": ["properties", "hs_time_in_customer"] - "companies": ["properties", "hs_time_in_evangelist"] - "companies": ["properties", "hs_time_in_lead"] - "companies": ["properties", "hs_time_in_marketingqualifiedlead"] - "companies": ["properties", "hs_time_in_opportunity"] - "companies": ["properties", "hs_time_in_other"] - "companies": ["properties", "hs_time_in_salesqualifiedlead"] - "companies": ["properties", "hs_time_in_subscriber"] - "contacts": ["properties", "hs_time_in_customer"] - "contacts": ["properties", "hs_time_in_evangelist"] - "contacts": ["properties", "hs_time_in_lead"] - "contacts": ["properties", "hs_time_in_marketingqualifiedlead"] - "contacts": ["properties", "hs_time_in_opportunity"] - "contacts": ["properties", "hs_time_in_other"] - "contacts": ["properties", "hs_time_in_salesqualifiedlead"] - "contacts": ["properties", "hs_time_in_subscriber"] - "deals": ["properties", "hs_time_in_9567448"] - "deals": ["properties", "hs_time_in_9567449"] - "deals": ["properties", "hs_time_in_appointmentscheduled"] - "deals": ["properties", "hs_time_in_closedlost"] - "deals": ["properties", "hs_time_in_closedwon"] - "deals": ["properties", "hs_time_in_contractsent"] - "deals": ["properties", "hs_time_in_customclosedwonstage"] - "deals": ["properties", "hs_time_in_decisionmakerboughtin"] - "deals": ["properties", "hs_time_in_presentationscheduled"] - "deals": ["properties", "hs_time_in_qualifiedtobuy"] - "tickets": ["properties", "hs_time_in_1"] - "tickets": ["properties", "hs_time_in_2"] - "tickets": ["properties", "hs_time_in_3"] - "tickets": ["properties", "hs_time_in_4"] - "property_history": ["property", "hs_time_in_lead"] - "property_history": ["property", "hs_time_in_subscriber"] + # This config is the same as for basic read except for missing `property_history` stream. + # This stream emits records with dynamic timestamps under some conditions + # (properties like `hs_time_in_lead`, `hs_time_in_subscriber` etc.) which makes it impossible to compare records. + # Ignoring these fields makes testing this stream senseless because those valuable values of other property types + # will also be ignored. Instead, we test this stream against expected records in basic read test. + configured_catalog_path: "sample_files/full_refresh_oauth_catalog.json" \ No newline at end of file diff --git a/airbyte-integrations/connectors/source-hubspot/integration_tests/abnormal_state.json b/airbyte-integrations/connectors/source-hubspot/integration_tests/abnormal_state.json index 0b6c4fc743103..a253d73ae5db1 100644 --- a/airbyte-integrations/connectors/source-hubspot/integration_tests/abnormal_state.json +++ b/airbyte-integrations/connectors/source-hubspot/integration_tests/abnormal_state.json @@ -49,5 +49,8 @@ }, "tickets": { "updatedAt": "2221-10-12T13:37:56.412000+00:00" + }, + "property_history": { + "timestamp": 7966012325000 } } diff --git a/airbyte-integrations/connectors/source-hubspot/integration_tests/expected_records.txt b/airbyte-integrations/connectors/source-hubspot/integration_tests/expected_records.txt new file mode 100644 index 0000000000000..e8586787f8eb9 --- /dev/null +++ b/airbyte-integrations/connectors/source-hubspot/integration_tests/expected_records.txt @@ -0,0 +1,148 @@ +{"stream": "property_history", "data": {"value": "0", "source-type": "MIGRATION", "source-id": "BackfillReadtimeCalculatedPropertiesJob", "source-label": null, "updated-by-user-id": null, "timestamp": 1628718463905, "selected": false, "property": "num_unique_conversion_events", "vid": 501}, "emitted_at": 1654677520163} +{"stream": "property_history", "data": {"value": "1616173106539", "source-type": "CONTACTS", "source-id": "CRM_UI", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106539, "selected": false, "property": "createdate", "vid": 501}, "emitted_at": 1654677520165} +{"stream": "property_history", "data": {"value": "52550153", "source-type": "CRM_UI", "source-id": "userId:12282590", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106523, "selected": false, "property": "hubspot_owner_id", "vid": 501}, "emitted_at": 1654677520167} +{"stream": "property_history", "data": {"value": "1621592488593", "source-type": "DEALS", "source-id": "DealRollupProperties", "source-label": null, "updated-by-user-id": null, "timestamp": 1621592560527, "selected": false, "property": "first_deal_created_date", "vid": 501}, "emitted_at": 1654677520168} +{"stream": "property_history", "data": {"value": "1", "source-type": "DEALS", "source-id": "DealRollupProperties", "source-label": null, "updated-by-user-id": null, "timestamp": 1621592560527, "selected": false, "property": "num_associated_deals", "vid": 501}, "emitted_at": 1654677520169} +{"stream": "property_history", "data": {"value": "Kulak", "source-type": "CRM_UI", "source-id": "userId:12282590", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106523, "selected": false, "property": "lastname", "vid": 501}, "emitted_at": 1654677520175} +{"stream": "property_history", "data": {"value": "1111111111", "source-type": "CRM_UI", "source-id": "userId:12282590", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106523, "selected": false, "property": "phone", "vid": 501}, "emitted_at": 1654677520178} +{"stream": "property_history", "data": {"value": "0", "source-type": "MIGRATION", "source-id": "BackfillReadtimeCalculatedPropertiesJob", "source-label": null, "updated-by-user-id": null, "timestamp": 1628718463905, "selected": false, "property": "num_conversion_events", "vid": 501}, "emitted_at": 1654677520181} +{"stream": "property_history", "data": {"value": "Eugene", "source-type": "CRM_UI", "source-id": "userId:12282590", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106523, "selected": false, "property": "firstname", "vid": 501}, "emitted_at": 1654677520188} +{"stream": "property_history", "data": {"value": "california", "source-type": "HEISENBERG", "source-id": "EMAIL_OPEN (9ff40077-4b32-3ec5-9aea-d69fd12683b9)", "source-label": null, "updated-by-user-id": null, "timestamp": 1616173245743, "selected": false, "property": "ip_state", "vid": 501}, "emitted_at": 1654677520189} +{"stream": "property_history", "data": {"value": "united states", "source-type": "HEISENBERG", "source-id": "EMAIL_OPEN (9ff40077-4b32-3ec5-9aea-d69fd12683b9)", "source-label": null, "updated-by-user-id": null, "timestamp": 1616173245743, "selected": false, "property": "ip_country", "vid": 501}, "emitted_at": 1654677520190} +{"stream": "property_history", "data": {"value": "ca", "source-type": "HEISENBERG", "source-id": "EMAIL_OPEN (9ff40077-4b32-3ec5-9aea-d69fd12683b9)", "source-label": null, "updated-by-user-id": null, "timestamp": 1616173245743, "selected": false, "property": "ip_state_code", "vid": 501}, "emitted_at": 1654677520193} +{"stream": "property_history", "data": {"value": "kulak.eugene@gmail.com", "source-type": "CONTACTS", "source-id": "CRM_UI", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106539, "selected": false, "property": "email", "vid": 501}, "emitted_at": 1654677520197} +{"stream": "property_history", "data": {"value": "us", "source-type": "HEISENBERG", "source-id": "EMAIL_OPEN (9ff40077-4b32-3ec5-9aea-d69fd12683b9)", "source-label": null, "updated-by-user-id": null, "timestamp": 1616173245743, "selected": false, "property": "ip_country_code", "vid": 501}, "emitted_at": 1654677520198} +{"stream": "property_history", "data": {"value": "mountain view", "source-type": "HEISENBERG", "source-id": "EMAIL_OPEN (9ff40077-4b32-3ec5-9aea-d69fd12683b9)", "source-label": null, "updated-by-user-id": null, "timestamp": 1616173245743, "selected": false, "property": "ip_city", "vid": 501}, "emitted_at": 1654677520201} +{"stream": "property_history", "data": {"value": "1616173106523", "source-type": "CRM_UI", "source-id": "userId:12282590", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106523, "selected": false, "property": "hubspot_owner_assigneddate", "vid": 501}, "emitted_at": 1654677520201} +{"stream": "property_history", "data": {"value": "opportunity", "source-type": "DEALS", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1621592560659, "selected": false, "property": "lifecyclestage", "vid": 501}, "emitted_at": 1654677520202} +{"stream": "property_history", "data": {"value": "subscriber", "source-type": "CRM_UI", "source-id": "userId:12282590", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106523, "selected": false, "property": "lifecyclestage", "vid": 501}, "emitted_at": 1654677520203} +{"stream": "property_history", "data": {"value": "test contact 0", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "firstname", "vid": 601}, "emitted_at": 1654677520205} +{"stream": "property_history", "data": {"value": "Cambridge", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "city", "vid": 601}, "emitted_at": 1654677520205} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044971482, "selected": false, "property": "num_unique_conversion_events", "vid": 601}, "emitted_at": 1654677520205} +{"stream": "property_history", "data": {"value": "1634044970930", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970930, "selected": false, "property": "createdate", "vid": 601}, "emitted_at": 1654677520207} +{"stream": "property_history", "data": {"value": "HubSpot Test", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "company", "vid": 601}, "emitted_at": 1654677520211} +{"stream": "property_history", "data": {"value": "MA", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "state", "vid": 601}, "emitted_at": 1654677520211} +{"stream": "property_history", "data": {"value": "testingapicontact_0@hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970930, "selected": false, "property": "email", "vid": 601}, "emitted_at": 1654677520212} +{"stream": "property_history", "data": {"value": "02139", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "zip", "vid": 601}, "emitted_at": 1654677520212} +{"stream": "property_history", "data": {"value": "http://hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "website", "vid": 601}, "emitted_at": 1654677520212} +{"stream": "property_history", "data": {"value": "0 First Street", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "address", "vid": 601}, "emitted_at": 1654677520213} +{"stream": "property_history", "data": {"value": "testerson number 0", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "lastname", "vid": 601}, "emitted_at": 1654677520214} +{"stream": "property_history", "data": {"value": "555-122-2323", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "phone", "vid": 601}, "emitted_at": 1654677520215} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044971482, "selected": false, "property": "num_conversion_events", "vid": 601}, "emitted_at": 1654677520215} +{"stream": "property_history", "data": {"value": "subscriber", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970930, "selected": false, "property": "lifecyclestage", "vid": 601}, "emitted_at": 1654677520216} +{"stream": "property_history", "data": {"value": "test contact 10", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "firstname", "vid": 1101}, "emitted_at": 1654677520217} +{"stream": "property_history", "data": {"value": "Cambridge", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "city", "vid": 1101}, "emitted_at": 1654677520217} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988327, "selected": false, "property": "num_unique_conversion_events", "vid": 1101}, "emitted_at": 1654677520217} +{"stream": "property_history", "data": {"value": "1634044988089", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988089, "selected": false, "property": "createdate", "vid": 1101}, "emitted_at": 1654677520218} +{"stream": "property_history", "data": {"value": "HubSpot Test", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "company", "vid": 1101}, "emitted_at": 1654677520219} +{"stream": "property_history", "data": {"value": "MA", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "state", "vid": 1101}, "emitted_at": 1654677520219} +{"stream": "property_history", "data": {"value": "testingapicontact_10@hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988089, "selected": false, "property": "email", "vid": 1101}, "emitted_at": 1654677520220} +{"stream": "property_history", "data": {"value": "02139", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "zip", "vid": 1101}, "emitted_at": 1654677520220} +{"stream": "property_history", "data": {"value": "http://hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "website", "vid": 1101}, "emitted_at": 1654677520220} +{"stream": "property_history", "data": {"value": "10 First Street", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "address", "vid": 1101}, "emitted_at": 1654677520220} +{"stream": "property_history", "data": {"value": "testerson number 10", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "lastname", "vid": 1101}, "emitted_at": 1654677520221} +{"stream": "property_history", "data": {"value": "555-122-2323", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "phone", "vid": 1101}, "emitted_at": 1654677520222} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988327, "selected": false, "property": "num_conversion_events", "vid": 1101}, "emitted_at": 1654677520223} +{"stream": "property_history", "data": {"value": "subscriber", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988089, "selected": false, "property": "lifecyclestage", "vid": 1101}, "emitted_at": 1654677520224} +{"stream": "property_history", "data": {"value": "test contact 1", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "firstname", "vid": 651}, "emitted_at": 1654677520225} +{"stream": "property_history", "data": {"value": "Cambridge", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "city", "vid": 651}, "emitted_at": 1654677520225} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044982142, "selected": false, "property": "num_unique_conversion_events", "vid": 651}, "emitted_at": 1654677520225} +{"stream": "property_history", "data": {"value": "1634044981830", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981830, "selected": false, "property": "createdate", "vid": 651}, "emitted_at": 1654677520226} +{"stream": "property_history", "data": {"value": "HubSpot Test", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "company", "vid": 651}, "emitted_at": 1654677520228} +{"stream": "property_history", "data": {"value": "MA", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "state", "vid": 651}, "emitted_at": 1654677520229} +{"stream": "property_history", "data": {"value": "testingapicontact_1@hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981830, "selected": false, "property": "email", "vid": 651}, "emitted_at": 1654677520229} +{"stream": "property_history", "data": {"value": "02139", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "zip", "vid": 651}, "emitted_at": 1654677520229} +{"stream": "property_history", "data": {"value": "http://hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "website", "vid": 651}, "emitted_at": 1654677520229} +{"stream": "property_history", "data": {"value": "1 First Street", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "address", "vid": 651}, "emitted_at": 1654677520229} +{"stream": "property_history", "data": {"value": "testerson number 1", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "lastname", "vid": 651}, "emitted_at": 1654677520230} +{"stream": "property_history", "data": {"value": "555-122-2323", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "phone", "vid": 651}, "emitted_at": 1654677520230} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044982142, "selected": false, "property": "num_conversion_events", "vid": 651}, "emitted_at": 1654677520231} +{"stream": "property_history", "data": {"value": "subscriber", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981830, "selected": false, "property": "lifecyclestage", "vid": 651}, "emitted_at": 1654677520231} +{"stream": "property_history", "data": {"value": "test contact 8", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "firstname", "vid": 1001}, "emitted_at": 1654677520232} +{"stream": "property_history", "data": {"value": "Cambridge", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "city", "vid": 1001}, "emitted_at": 1654677520232} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044987352, "selected": false, "property": "num_unique_conversion_events", "vid": 1001}, "emitted_at": 1654677520232} +{"stream": "property_history", "data": {"value": "1634044986974", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986974, "selected": false, "property": "createdate", "vid": 1001}, "emitted_at": 1654677520233} +{"stream": "property_history", "data": {"value": "HubSpot Test", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "company", "vid": 1001}, "emitted_at": 1654677520234} +{"stream": "property_history", "data": {"value": "MA", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "state", "vid": 1001}, "emitted_at": 1654677520234} +{"stream": "property_history", "data": {"value": "testingapicontact_8@hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986974, "selected": false, "property": "email", "vid": 1001}, "emitted_at": 1654677520234} +{"stream": "property_history", "data": {"value": "02139", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "zip", "vid": 1001}, "emitted_at": 1654677520234} +{"stream": "property_history", "data": {"value": "http://hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "website", "vid": 1001}, "emitted_at": 1654677520235} +{"stream": "property_history", "data": {"value": "8 First Street", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "address", "vid": 1001}, "emitted_at": 1654677520235} +{"stream": "property_history", "data": {"value": "testerson number 8", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "lastname", "vid": 1001}, "emitted_at": 1654677520235} +{"stream": "property_history", "data": {"value": "555-122-2323", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "phone", "vid": 1001}, "emitted_at": 1654677520236} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044987352, "selected": false, "property": "num_conversion_events", "vid": 1001}, "emitted_at": 1654677520236} +{"stream": "property_history", "data": {"value": "subscriber", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986974, "selected": false, "property": "lifecyclestage", "vid": 1001}, "emitted_at": 1654677520237} +{"stream": "property_history", "data": {"value": "0", "source-type": "MIGRATION", "source-id": "BackfillReadtimeCalculatedPropertiesJob", "source-label": null, "updated-by-user-id": null, "timestamp": 1628718463905, "selected": false, "property": "num_unique_conversion_events", "vid": 501}, "emitted_at": 1654677520163} +{"stream": "property_history", "data": {"value": "1616173106539", "source-type": "CONTACTS", "source-id": "CRM_UI", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106539, "selected": false, "property": "createdate", "vid": 501}, "emitted_at": 1654677520165} +{"stream": "property_history", "data": {"value": "52550153", "source-type": "CRM_UI", "source-id": "userId:12282590", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106523, "selected": false, "property": "hubspot_owner_id", "vid": 501}, "emitted_at": 1654677520167} +{"stream": "property_history", "data": {"value": "1621592488593", "source-type": "DEALS", "source-id": "DealRollupProperties", "source-label": null, "updated-by-user-id": null, "timestamp": 1621592560527, "selected": false, "property": "first_deal_created_date", "vid": 501}, "emitted_at": 1654677520168} +{"stream": "property_history", "data": {"value": "1", "source-type": "DEALS", "source-id": "DealRollupProperties", "source-label": null, "updated-by-user-id": null, "timestamp": 1621592560527, "selected": false, "property": "num_associated_deals", "vid": 501}, "emitted_at": 1654677520169} +{"stream": "property_history", "data": {"value": "Kulak", "source-type": "CRM_UI", "source-id": "userId:12282590", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106523, "selected": false, "property": "lastname", "vid": 501}, "emitted_at": 1654677520175} +{"stream": "property_history", "data": {"value": "1111111111", "source-type": "CRM_UI", "source-id": "userId:12282590", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106523, "selected": false, "property": "phone", "vid": 501}, "emitted_at": 1654677520178} +{"stream": "property_history", "data": {"value": "0", "source-type": "MIGRATION", "source-id": "BackfillReadtimeCalculatedPropertiesJob", "source-label": null, "updated-by-user-id": null, "timestamp": 1628718463905, "selected": false, "property": "num_conversion_events", "vid": 501}, "emitted_at": 1654677520181} +{"stream": "property_history", "data": {"value": "Eugene", "source-type": "CRM_UI", "source-id": "userId:12282590", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106523, "selected": false, "property": "firstname", "vid": 501}, "emitted_at": 1654677520188} +{"stream": "property_history", "data": {"value": "california", "source-type": "HEISENBERG", "source-id": "EMAIL_OPEN (9ff40077-4b32-3ec5-9aea-d69fd12683b9)", "source-label": null, "updated-by-user-id": null, "timestamp": 1616173245743, "selected": false, "property": "ip_state", "vid": 501}, "emitted_at": 1654677520189} +{"stream": "property_history", "data": {"value": "united states", "source-type": "HEISENBERG", "source-id": "EMAIL_OPEN (9ff40077-4b32-3ec5-9aea-d69fd12683b9)", "source-label": null, "updated-by-user-id": null, "timestamp": 1616173245743, "selected": false, "property": "ip_country", "vid": 501}, "emitted_at": 1654677520190} +{"stream": "property_history", "data": {"value": "ca", "source-type": "HEISENBERG", "source-id": "EMAIL_OPEN (9ff40077-4b32-3ec5-9aea-d69fd12683b9)", "source-label": null, "updated-by-user-id": null, "timestamp": 1616173245743, "selected": false, "property": "ip_state_code", "vid": 501}, "emitted_at": 1654677520193} +{"stream": "property_history", "data": {"value": "kulak.eugene@gmail.com", "source-type": "CONTACTS", "source-id": "CRM_UI", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106539, "selected": false, "property": "email", "vid": 501}, "emitted_at": 1654677520197} +{"stream": "property_history", "data": {"value": "us", "source-type": "HEISENBERG", "source-id": "EMAIL_OPEN (9ff40077-4b32-3ec5-9aea-d69fd12683b9)", "source-label": null, "updated-by-user-id": null, "timestamp": 1616173245743, "selected": false, "property": "ip_country_code", "vid": 501}, "emitted_at": 1654677520198} +{"stream": "property_history", "data": {"value": "mountain view", "source-type": "HEISENBERG", "source-id": "EMAIL_OPEN (9ff40077-4b32-3ec5-9aea-d69fd12683b9)", "source-label": null, "updated-by-user-id": null, "timestamp": 1616173245743, "selected": false, "property": "ip_city", "vid": 501}, "emitted_at": 1654677520201} +{"stream": "property_history", "data": {"value": "1616173106523", "source-type": "CRM_UI", "source-id": "userId:12282590", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106523, "selected": false, "property": "hubspot_owner_assigneddate", "vid": 501}, "emitted_at": 1654677520201} +{"stream": "property_history", "data": {"value": "opportunity", "source-type": "DEALS", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1621592560659, "selected": false, "property": "lifecyclestage", "vid": 501}, "emitted_at": 1654677520202} +{"stream": "property_history", "data": {"value": "subscriber", "source-type": "CRM_UI", "source-id": "userId:12282590", "source-label": null, "updated-by-user-id": 12282590, "timestamp": 1616173106523, "selected": false, "property": "lifecyclestage", "vid": 501}, "emitted_at": 1654677520203} +{"stream": "property_history", "data": {"value": "test contact 0", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "firstname", "vid": 601}, "emitted_at": 1654677520205} +{"stream": "property_history", "data": {"value": "Cambridge", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "city", "vid": 601}, "emitted_at": 1654677520205} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044971482, "selected": false, "property": "num_unique_conversion_events", "vid": 601}, "emitted_at": 1654677520205} +{"stream": "property_history", "data": {"value": "1634044970930", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970930, "selected": false, "property": "createdate", "vid": 601}, "emitted_at": 1654677520207} +{"stream": "property_history", "data": {"value": "HubSpot Test", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "company", "vid": 601}, "emitted_at": 1654677520211} +{"stream": "property_history", "data": {"value": "MA", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "state", "vid": 601}, "emitted_at": 1654677520211} +{"stream": "property_history", "data": {"value": "testingapicontact_0@hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970930, "selected": false, "property": "email", "vid": 601}, "emitted_at": 1654677520212} +{"stream": "property_history", "data": {"value": "02139", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "zip", "vid": 601}, "emitted_at": 1654677520212} +{"stream": "property_history", "data": {"value": "http://hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "website", "vid": 601}, "emitted_at": 1654677520212} +{"stream": "property_history", "data": {"value": "0 First Street", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "address", "vid": 601}, "emitted_at": 1654677520213} +{"stream": "property_history", "data": {"value": "testerson number 0", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "lastname", "vid": 601}, "emitted_at": 1654677520214} +{"stream": "property_history", "data": {"value": "555-122-2323", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970920, "selected": false, "property": "phone", "vid": 601}, "emitted_at": 1654677520215} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044971482, "selected": false, "property": "num_conversion_events", "vid": 601}, "emitted_at": 1654677520215} +{"stream": "property_history", "data": {"value": "subscriber", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044970930, "selected": false, "property": "lifecyclestage", "vid": 601}, "emitted_at": 1654677520216} +{"stream": "property_history", "data": {"value": "test contact 10", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "firstname", "vid": 1101}, "emitted_at": 1654677520217} +{"stream": "property_history", "data": {"value": "Cambridge", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "city", "vid": 1101}, "emitted_at": 1654677520217} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988327, "selected": false, "property": "num_unique_conversion_events", "vid": 1101}, "emitted_at": 1654677520217} +{"stream": "property_history", "data": {"value": "1634044988089", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988089, "selected": false, "property": "createdate", "vid": 1101}, "emitted_at": 1654677520218} +{"stream": "property_history", "data": {"value": "HubSpot Test", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "company", "vid": 1101}, "emitted_at": 1654677520219} +{"stream": "property_history", "data": {"value": "MA", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "state", "vid": 1101}, "emitted_at": 1654677520219} +{"stream": "property_history", "data": {"value": "testingapicontact_10@hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988089, "selected": false, "property": "email", "vid": 1101}, "emitted_at": 1654677520220} +{"stream": "property_history", "data": {"value": "02139", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "zip", "vid": 1101}, "emitted_at": 1654677520220} +{"stream": "property_history", "data": {"value": "http://hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "website", "vid": 1101}, "emitted_at": 1654677520220} +{"stream": "property_history", "data": {"value": "10 First Street", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "address", "vid": 1101}, "emitted_at": 1654677520220} +{"stream": "property_history", "data": {"value": "testerson number 10", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "lastname", "vid": 1101}, "emitted_at": 1654677520221} +{"stream": "property_history", "data": {"value": "555-122-2323", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988081, "selected": false, "property": "phone", "vid": 1101}, "emitted_at": 1654677520222} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988327, "selected": false, "property": "num_conversion_events", "vid": 1101}, "emitted_at": 1654677520223} +{"stream": "property_history", "data": {"value": "subscriber", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044988089, "selected": false, "property": "lifecyclestage", "vid": 1101}, "emitted_at": 1654677520224} +{"stream": "property_history", "data": {"value": "test contact 1", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "firstname", "vid": 651}, "emitted_at": 1654677520225} +{"stream": "property_history", "data": {"value": "Cambridge", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "city", "vid": 651}, "emitted_at": 1654677520225} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044982142, "selected": false, "property": "num_unique_conversion_events", "vid": 651}, "emitted_at": 1654677520225} +{"stream": "property_history", "data": {"value": "1634044981830", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981830, "selected": false, "property": "createdate", "vid": 651}, "emitted_at": 1654677520226} +{"stream": "property_history", "data": {"value": "HubSpot Test", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "company", "vid": 651}, "emitted_at": 1654677520228} +{"stream": "property_history", "data": {"value": "MA", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "state", "vid": 651}, "emitted_at": 1654677520229} +{"stream": "property_history", "data": {"value": "testingapicontact_1@hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981830, "selected": false, "property": "email", "vid": 651}, "emitted_at": 1654677520229} +{"stream": "property_history", "data": {"value": "02139", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "zip", "vid": 651}, "emitted_at": 1654677520229} +{"stream": "property_history", "data": {"value": "http://hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "website", "vid": 651}, "emitted_at": 1654677520229} +{"stream": "property_history", "data": {"value": "1 First Street", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "address", "vid": 651}, "emitted_at": 1654677520229} +{"stream": "property_history", "data": {"value": "testerson number 1", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "lastname", "vid": 651}, "emitted_at": 1654677520230} +{"stream": "property_history", "data": {"value": "555-122-2323", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981822, "selected": false, "property": "phone", "vid": 651}, "emitted_at": 1654677520230} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044982142, "selected": false, "property": "num_conversion_events", "vid": 651}, "emitted_at": 1654677520231} +{"stream": "property_history", "data": {"value": "subscriber", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044981830, "selected": false, "property": "lifecyclestage", "vid": 651}, "emitted_at": 1654677520231} +{"stream": "property_history", "data": {"value": "test contact 8", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "firstname", "vid": 1001}, "emitted_at": 1654677520232} +{"stream": "property_history", "data": {"value": "Cambridge", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "city", "vid": 1001}, "emitted_at": 1654677520232} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044987352, "selected": false, "property": "num_unique_conversion_events", "vid": 1001}, "emitted_at": 1654677520232} +{"stream": "property_history", "data": {"value": "1634044986974", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986974, "selected": false, "property": "createdate", "vid": 1001}, "emitted_at": 1654677520233} +{"stream": "property_history", "data": {"value": "HubSpot Test", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "company", "vid": 1001}, "emitted_at": 1654677520234} +{"stream": "property_history", "data": {"value": "MA", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "state", "vid": 1001}, "emitted_at": 1654677520234} +{"stream": "property_history", "data": {"value": "testingapicontact_8@hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986974, "selected": false, "property": "email", "vid": 1001}, "emitted_at": 1654677520234} +{"stream": "property_history", "data": {"value": "02139", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "zip", "vid": 1001}, "emitted_at": 1654677520234} +{"stream": "property_history", "data": {"value": "http://hubspot.com", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "website", "vid": 1001}, "emitted_at": 1654677520235} +{"stream": "property_history", "data": {"value": "8 First Street", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "address", "vid": 1001}, "emitted_at": 1654677520235} +{"stream": "property_history", "data": {"value": "testerson number 8", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "lastname", "vid": 1001}, "emitted_at": 1654677520235} +{"stream": "property_history", "data": {"value": "555-122-2323", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986968, "selected": false, "property": "phone", "vid": 1001}, "emitted_at": 1654677520236} +{"stream": "property_history", "data": {"value": "0", "source-type": "CALCULATED", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044987352, "selected": false, "property": "num_conversion_events", "vid": 1001}, "emitted_at": 1654677520236} +{"stream": "property_history", "data": {"value": "subscriber", "source-type": "API", "source-id": null, "source-label": null, "updated-by-user-id": null, "timestamp": 1634044986974, "selected": false, "property": "lifecyclestage", "vid": 1001}, "emitted_at": 1654677520237} \ No newline at end of file diff --git a/airbyte-integrations/connectors/source-hubspot/sample_files/basic_read_catalog.json b/airbyte-integrations/connectors/source-hubspot/sample_files/basic_read_catalog.json new file mode 100644 index 0000000000000..aeccc52d02f79 --- /dev/null +++ b/airbyte-integrations/connectors/source-hubspot/sample_files/basic_read_catalog.json @@ -0,0 +1,166 @@ +{ + "streams": [ + { + "stream": { + "name": "campaigns", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "companies", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "contact_lists", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "contacts", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "contacts_list_memberships", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "deal_pipelines", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "deals", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "engagements", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "forms", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "form_submissions", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "line_items", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "owners", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "products", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "property_history", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "quotes", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "tickets", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "ticket_pipelines", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "workflows", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + } + ] +} diff --git a/airbyte-integrations/connectors/source-hubspot/sample_files/configured_catalog_for_oauth_config.json b/airbyte-integrations/connectors/source-hubspot/sample_files/basic_read_oauth_catalog.json similarity index 100% rename from airbyte-integrations/connectors/source-hubspot/sample_files/configured_catalog_for_oauth_config.json rename to airbyte-integrations/connectors/source-hubspot/sample_files/basic_read_oauth_catalog.json diff --git a/airbyte-integrations/connectors/source-hubspot/sample_files/full_refresh_catalog.json b/airbyte-integrations/connectors/source-hubspot/sample_files/full_refresh_catalog.json index aeccc52d02f79..76b06a1c7dd24 100644 --- a/airbyte-integrations/connectors/source-hubspot/sample_files/full_refresh_catalog.json +++ b/airbyte-integrations/connectors/source-hubspot/sample_files/full_refresh_catalog.json @@ -117,15 +117,6 @@ "sync_mode": "full_refresh", "destination_sync_mode": "overwrite" }, - { - "stream": { - "name": "property_history", - "json_schema": {}, - "supported_sync_modes": ["full_refresh"] - }, - "sync_mode": "full_refresh", - "destination_sync_mode": "overwrite" - }, { "stream": { "name": "quotes", diff --git a/airbyte-integrations/connectors/source-hubspot/sample_files/full_refresh_oauth_catalog.json b/airbyte-integrations/connectors/source-hubspot/sample_files/full_refresh_oauth_catalog.json new file mode 100644 index 0000000000000..6738ba2a8b3c4 --- /dev/null +++ b/airbyte-integrations/connectors/source-hubspot/sample_files/full_refresh_oauth_catalog.json @@ -0,0 +1,184 @@ +{ + "streams": [ + { + "stream": { + "name": "campaigns", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "companies", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "contact_lists", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "contacts", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "contacts_list_memberships", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "deal_pipelines", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "deals", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "email_events", + "json_schema": {}, + "supported_sync_modes": ["full_refresh", "incremental"], + "source_defined_cursor": true, + "default_cursor_field": ["created"] + }, + "sync_mode": "full_refresh", + "cursor_field": ["created"], + "destination_sync_mode": "append" + }, + { + "stream": { + "name": "engagements", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "form_submissions", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "forms", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "form_submissions", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "line_items", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "marketing_emails", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"], + "source_defined_cursor": false, + "default_cursor_field": ["updated"] + }, + "sync_mode": "full_refresh", + "cursor_field": null, + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "owners", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "products", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "subscription_changes", + "json_schema": {}, + "supported_sync_modes": ["full_refresh", "incremental"], + "source_defined_cursor": true, + "default_cursor_field": ["timestamp"] + }, + "sync_mode": "full_refresh", + "cursor_field": ["timestamp"], + "destination_sync_mode": "append" + }, + { + "stream": { + "name": "tickets", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + }, + { + "stream": { + "name": "workflows", + "json_schema": {}, + "supported_sync_modes": ["full_refresh"] + }, + "sync_mode": "full_refresh", + "destination_sync_mode": "overwrite" + } + ] +} diff --git a/airbyte-integrations/connectors/source-hubspot/sample_files/configured_catalog.json b/airbyte-integrations/connectors/source-hubspot/sample_files/incremental_catalog.json similarity index 99% rename from airbyte-integrations/connectors/source-hubspot/sample_files/configured_catalog.json rename to airbyte-integrations/connectors/source-hubspot/sample_files/incremental_catalog.json index de022f5436668..cd68c0f9a1bb7 100644 --- a/airbyte-integrations/connectors/source-hubspot/sample_files/configured_catalog.json +++ b/airbyte-integrations/connectors/source-hubspot/sample_files/incremental_catalog.json @@ -232,7 +232,7 @@ "supported_sync_modes": ["full_refresh", "incremental"], "default_cursor_field": ["timestamp"] }, - "sync_mode": "full_refresh", + "sync_mode": "incremental", "cursor_field": ["timestamp"], "destination_sync_mode": "overwrite" }, diff --git a/airbyte-integrations/connectors/source-hubspot/source_hubspot/helpers.py b/airbyte-integrations/connectors/source-hubspot/source_hubspot/helpers.py new file mode 100644 index 0000000000000..74c861106a434 --- /dev/null +++ b/airbyte-integrations/connectors/source-hubspot/source_hubspot/helpers.py @@ -0,0 +1,47 @@ +# +# Copyright (c) 2022 Airbyte, Inc., all rights reserved. +# + +import abc +from typing import MutableMapping + + +class IRecordPostProcessor(abc.ABC): + @abc.abstractmethod + def add_record(self, record: MutableMapping, primary_key: str = None): + """""" + + @property + @abc.abstractmethod + def flat(self): + """""" + + +class GroupByKey(IRecordPostProcessor): + def __init__(self): + self._storage = {} + + def add_record(self, record: MutableMapping, primary_key: str = None): + record_pk = record[primary_key] + if record_pk not in self._storage: + self._storage[record_pk] = record + stored_props = self._storage[record_pk].get("properties") + if stored_props: + stored_props.update(record.get("properties", {})) + self._storage[record_pk]["properties"] = stored_props + + @property + def flat(self): + return list(self._storage.values()) + + +class StoreAsIs(IRecordPostProcessor): + def __init__(self): + self._storage = [] + + def add_record(self, record: MutableMapping, primary_key: str = None): + self._storage.append(record) + + @property + def flat(self): + return self._storage diff --git a/airbyte-integrations/connectors/source-hubspot/source_hubspot/schemas/property_history.json b/airbyte-integrations/connectors/source-hubspot/source_hubspot/schemas/property_history.json index 13ae1f80322bd..97fd5c1e20db0 100644 --- a/airbyte-integrations/connectors/source-hubspot/source_hubspot/schemas/property_history.json +++ b/airbyte-integrations/connectors/source-hubspot/source_hubspot/schemas/property_history.json @@ -18,8 +18,7 @@ "type": ["null", "integer"] }, "timestamp": { - "type": ["null", "string"], - "format": "date-time" + "type": ["null", "integer"] }, "selected": { "type": ["null", "boolean"] diff --git a/airbyte-integrations/connectors/source-hubspot/source_hubspot/streams.py b/airbyte-integrations/connectors/source-hubspot/source_hubspot/streams.py index bb8dbb737b6cc..45f03eca1a6b7 100644 --- a/airbyte-integrations/connectors/source-hubspot/source_hubspot/streams.py +++ b/airbyte-integrations/connectors/source-hubspot/source_hubspot/streams.py @@ -7,7 +7,7 @@ import time import urllib.parse from abc import ABC, abstractmethod -from functools import lru_cache, partial +from functools import lru_cache from http import HTTPStatus from typing import Any, Dict, Iterable, Iterator, List, Mapping, MutableMapping, Optional, Set, Tuple, Union @@ -22,6 +22,7 @@ from airbyte_cdk.sources.utils.transform import TransformConfig, TypeTransformer from requests import codes from source_hubspot.errors import HubspotAccessDenied, HubspotInvalidAuth, HubspotRateLimited, HubspotTimeout +from source_hubspot.helpers import GroupByKey, IRecordPostProcessor, StoreAsIs # The value is obtained experimentally, HubSpot allows the URL length up to ~16300 symbols, # so it was decided to limit the length of the `properties` parameter to 15000 characters. @@ -75,6 +76,13 @@ def split_properties(properties_list: List[str]) -> Iterator[Tuple[str]]: yield local_properties +def too_many_properties(properties_list: List[str]) -> bool: + # Do not iterate over the generator until the end. Here we need to know if it produces more than one record + generator = split_properties(properties_list) + _ = next(generator) + return next(generator, None) is not None + + def retry_connection_handler(**kwargs): """Retry helper, log each attempt""" @@ -220,6 +228,7 @@ class Stream(HttpStream, ABC): offset = 0 primary_key = None filter_old_records: bool = True + denormalize_records: bool = False # one record from API response can result in multiple records emitted @property @abstractmethod @@ -316,30 +325,27 @@ def _read_stream_records( stream_slice: Mapping[str, Any] = None, stream_state: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None, - ) -> Tuple[dict, Any]: + ) -> Tuple[List, Any]: - # TODO: Additional processing was added due to the fact that users receive 414 errors while syncing their streams (issues #3977 and #5835). - # We will need to fix this code when the HubSpot developers add the ability to use a special parameter to get all properties for an entity. - # According to HubSpot Community (https://community.hubspot.com/t5/APIs-Integrations/Get-all-contact-properties-without-explicitly-listing-them/m-p/447950) + # TODO: Additional processing was added due to the fact that users receive 414 errors while syncing their streams + # (issues #3977 and #5835). We will need to fix this code when the HubSpot developers add the ability to use a special parameter + # to get all properties for an entity. According to HubSpot Community + # (https://community.hubspot.com/t5/APIs-Integrations/Get-all-contact-properties-without-explicitly-listing-them/m-p/447950) # and the official documentation, this does not exist at the moment. - stream_records = {} + group_by_pk = self.primary_key and not self.denormalize_records + post_processor: IRecordPostProcessor = GroupByKey() if group_by_pk else StoreAsIs() response = None for properties in split_properties(properties_list): - params = {"properties": ",".join(properties)} - + params = {"property": properties} response = self.handle_request( stream_slice=stream_slice, stream_state=stream_state, next_page_token=next_page_token, params=params ) - for record in self._transform(self.parse_response(response, stream_state=stream_state)): - if record["id"] not in stream_records: - stream_records[record["id"]] = record - elif stream_records[record["id"]].get("properties"): - stream_records[record["id"]]["properties"].update(record.get("properties", {})) + post_processor.add_record(record, self.primary_key) - return stream_records, response + return post_processor.flat, response def read_records( self, @@ -357,17 +363,19 @@ def read_records( while not pagination_complete: properties_list = list(self.properties.keys()) - if properties_list: - stream_records, response = self._read_stream_records( + if properties_list and too_many_properties(properties_list): + records, response = self._read_stream_records( properties_list=properties_list, stream_slice=stream_slice, stream_state=stream_state, next_page_token=next_page_token, ) - records = [value for key, value in stream_records.items()] else: response = self.handle_request( - stream_slice=stream_slice, stream_state=stream_state, next_page_token=next_page_token + stream_slice=stream_slice, + stream_state=stream_state, + next_page_token=next_page_token, + params={"property": properties_list}, ) records = self._transform(self.parse_response(response, stream_state=stream_state, stream_slice=stream_slice)) @@ -785,7 +793,7 @@ def _process_search( stream_slice: Mapping[str, Any] = None, stream_state: Mapping[str, Any] = None, next_page_token: Mapping[str, Any] = None, - ) -> Tuple[dict, requests.Response]: + ) -> Tuple[List, requests.Response]: stream_records = {} payload = ( { @@ -804,7 +812,7 @@ def _process_search( for record in self._transform(self.parse_response(raw_response, stream_state=stream_state, stream_slice=stream_slice)): stream_records[record["id"]] = record - return stream_records, raw_response + return list(stream_records.values()), raw_response def read_records( self, @@ -823,7 +831,7 @@ def read_records( properties_list = list(self.properties.keys()) if self.state: - stream_records, raw_response = self._process_search( + records, raw_response = self._process_search( properties_list, next_page_token=next_page_token, stream_state=stream_state, @@ -831,14 +839,12 @@ def read_records( ) else: - stream_records, raw_response = self._read_stream_records( + records, raw_response = self._read_stream_records( properties_list=properties_list, stream_slice=stream_slice, stream_state=stream_state, next_page_token=next_page_token, ) - - records = [value for key, value in stream_records.items()] records = self._filter_old_records(records) records = self._flat_associations(records) @@ -1307,17 +1313,23 @@ class PropertyHistory(IncrementalStream): url = "/contacts/v1/lists/recently_updated/contacts/recent" updated_at_field = "timestamp" created_at_field = "timestamp" + entity = "contacts" data_field = "contacts" page_field = "vid-offset" page_filter = "vidOffset" + denormalize_records = True limit = 100 scopes = {"crm.objects.contacts.read"} - def list(self, fields) -> Iterable: - properties = self._api.get("/properties/v2/contact/properties") - properties_list = [single_property["name"] for single_property in properties] - params = {"propertyMode": "value_and_history", "property": properties_list} - yield from self.read(partial(self._api.get, url=self.url), params) + def request_params( + self, + stream_state: Mapping[str, Any], + stream_slice: Mapping[str, Any] = None, + next_page_token: Mapping[str, Any] = None, + ) -> MutableMapping[str, Any]: + params = super().request_params(stream_state, stream_slice, next_page_token) + params.update(propertyMode="value_and_history") + return params def _transform(self, records: Iterable) -> Iterable: for record in records: @@ -1335,7 +1347,6 @@ def _transform(self, records: Iterable) -> Iterable: continue if versions: for version in versions: - version["timestamp"] = self._field_to_datetime(version["timestamp"]).to_rfc3339_string() version["property"] = key version["vid"] = vid yield version diff --git a/airbyte-integrations/connectors/source-hubspot/unit_tests/test_source.py b/airbyte-integrations/connectors/source-hubspot/unit_tests/test_source.py index 9a7e616aee41b..c49839d10aba8 100644 --- a/airbyte-integrations/connectors/source-hubspot/unit_tests/test_source.py +++ b/airbyte-integrations/connectors/source-hubspot/unit_tests/test_source.py @@ -244,9 +244,10 @@ def test_stream_with_splitting_properties(self, requests_mock, api, fake_propert "status_code": 200, } ] + property_param_set = "&".join([f"property={prop}" for prop in property_slice]) requests_mock.register_uri( "GET", - f"{test_stream_url}?limit=100&properties={','.join(property_slice)}{f'&after={after_id}' if after_id else ''}", + f"{test_stream_url}?limit=100&{property_param_set}{f'&after={after_id}' if after_id else ''}", record_responses, ) after_id = id_list[-1] @@ -282,7 +283,8 @@ def test_stream_with_splitting_properties_with_pagination(self, requests_mock, c "status_code": 200, } ] - requests_mock.register_uri("GET", f"{test_stream.url}?properties={','.join(property_slice)}", record_responses) + property_param_set = "&".join([f"property={prop}" for prop in property_slice]) + requests_mock.register_uri("GET", f"{test_stream.url}?{property_param_set}", record_responses) stream_records = list(test_stream.read_records(sync_mode=SyncMode.incremental)) @@ -315,7 +317,8 @@ def test_stream_with_splitting_properties_with_new_record(self, requests_mock, c } ] test_stream._sync_mode = SyncMode.full_refresh - requests_mock.register_uri("GET", f"{test_stream.url}?properties={','.join(property_slice)}", record_responses) + property_param_set = "&".join([f"property={prop}" for prop in property_slice]) + requests_mock.register_uri("GET", f"{test_stream.url}?{property_param_set}", record_responses) test_stream._sync_mode = None ids_list.append("1092593513") diff --git a/docs/integrations/sources/hubspot.md b/docs/integrations/sources/hubspot.md index 5a8c3c5c16891..1afff3d0db868 100644 --- a/docs/integrations/sources/hubspot.md +++ b/docs/integrations/sources/hubspot.md @@ -133,6 +133,7 @@ HubSpot's API will [rate limit](https://developers.hubspot.com/docs/api/usage-de | Version | Date | Pull Request | Subject | |:--------|:-----------|:---------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------| +| 0.1.67 | 2022-06-08 | [00000](https://github.com/airbytehq/airbyte/pull/00000) | Fix for the `property_history` which did not emit records | | 0.1.66 | 2022-06-05 | [13475](https://github.com/airbytehq/airbyte/pull/13475) | Scope `crm.objects.feedback_submissions.read` added for `feedback_submissions` stream | | 0.1.65 | 2022-06-03 | [13455](https://github.com/airbytehq/airbyte/pull/13455) | Discover only returns streams for which required scopes were granted | | 0.1.64 | 2022-06-03 | [13218](https://github.com/airbytehq/airbyte/pull/13218) | Transform `contact_lists` data to comply with schema |