1
0
mirror of synced 2025-12-25 02:09:19 -05:00

refactor[source-snapchat-marketing]: migrate to low-code (#39507)

Co-authored-by: Alexandre Girard <alexandre@airbyte.io>
This commit is contained in:
Serhii Lazebnyi
2024-07-02 01:10:11 +02:00
committed by GitHub
parent 779d363b35
commit d0b76e94c6
24 changed files with 4989 additions and 2323 deletions

View File

@@ -0,0 +1,3 @@
[run]
omit =
source_snapchat_marketing/run.py

View File

@@ -2,77 +2,244 @@
{
"type": "STREAM",
"stream": {
"stream_state": {
"updated_at": "2221-01-01T00:00:00Z"
},
"stream_descriptor": {
"name": "adaccounts"
"name": "adaccounts",
"namespace": null
},
"stream_state": {
"states": [
{
"partition": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
},
"cursor": {
"updated_at": "2221-01-01T00:00:00.000Z"
}
}
]
}
}
},
{
"type": "STREAM",
"stream": {
"stream_state": {
"updated_at": "2221-01-01T00:00:00Z"
},
"stream_descriptor": {
"name": "creatives"
"name": "creatives",
"namespace": null
},
"stream_state": {
"states": [
{
"partition": {
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"updated_at": "2221-01-01T00:00:00.000Z"
}
},
{
"partition": {
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"updated_at": "2221-01-01T00:00:00.000Z"
}
}
]
}
}
},
{
"type": "STREAM",
"stream": {
"stream_state": {
"updated_at": "2221-01-01T00:00:00Z"
},
"stream_descriptor": {
"name": "media"
"name": "media",
"namespace": null
},
"stream_state": {
"states": [
{
"partition": {
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"updated_at": "2221-01-01T00:00:00.000Z"
}
},
{
"partition": {
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"updated_at": "2221-01-01T00:00:00.000Z"
}
}
]
}
}
},
{
"type": "STREAM",
"stream": {
"stream_state": {
"updated_at": "2221-01-01T00:00:00Z"
},
"stream_descriptor": {
"name": "campaigns"
"name": "campaigns",
"namespace": null
},
"stream_state": {
"states": [
{
"partition": {
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"updated_at": "2221-01-01T00:00:00.000Z"
}
},
{
"partition": {
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"updated_at": "2221-01-01T00:00:00.000Z"
}
}
]
}
}
},
{
"type": "STREAM",
"stream": {
"stream_state": {
"updated_at": "2221-01-01T00:00:00Z"
},
"stream_descriptor": {
"name": "ads"
"name": "ads",
"namespace": null
},
"stream_state": {
"states": [
{
"partition": {
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"updated_at": "2221-01-01T00:00:00.000Z"
}
},
{
"partition": {
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"updated_at": "2221-01-01T00:00:00.000Z"
}
}
]
}
}
},
{
"type": "STREAM",
"stream": {
"stream_state": {
"updated_at": "2221-01-01T00:00:00Z"
},
"stream_descriptor": {
"name": "adsquads"
"name": "adsquads",
"namespace": null
},
"stream_state": {
"states": [
{
"partition": {
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"updated_at": "2221-01-01T00:00:00.000Z"
}
},
{
"partition": {
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"updated_at": "2221-01-01T00:00:00.000Z"
}
}
]
}
}
},
{
"type": "STREAM",
"stream": {
"stream_state": {
"updated_at": "2221-01-01T00:00:00Z"
},
"stream_descriptor": {
"name": "segments"
"name": "segments",
"namespace": null
},
"stream_state": {
"states": [
{
"partition": {
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"updated_at": "2221-01-01T00:00:00.000Z"
}
},
{
"partition": {
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"updated_at": "2221-01-01T00:00:00.000Z"
}
}
]
}
}
}

View File

@@ -2,44 +2,178 @@
{
"type": "STREAM",
"stream": {
"stream_state": {
"start_time": "2221-07-05"
},
"stream_descriptor": {
"name": "adaccounts_stats_daily"
"name": "adaccounts_stats_daily",
"namespace": null
},
"stream_state": {
"states": [
{
"partition": {
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"start_time": "2221-01-01T00:00:00.000-07:00"
}
},
{
"partition": {
"id": "7a205dba-557f-4f00-82d7-c78853dcad39",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"start_time": "2221-01-01T00:00:00.000-07:00"
}
},
{
"partition": {
"id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
},
"cursor": {
"start_time": "2221-01-01T00:00:00.000-07:00"
}
}
]
}
}
},
{
"type": "STREAM",
"stream": {
"stream_state": {
"start_time": "2221-07-05"
},
"stream_descriptor": {
"name": "ads_stats_daily"
"name": "ads_stats_daily",
"namespace": null
},
"stream_state": {
"states": [
{
"partition": {
"ad_id": "96e5549f-4065-490e-93dd-ffb9f7973b77",
"parent_slice": {
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
}
},
"cursor": {
"start_time": "2221-01-01T00:00:00.000-07:00"
}
},
{
"partition": {
"id": "8831ae74-bd1e-4ea1-9628-76e549041bea",
"parent_slice": {
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
}
},
"cursor": {
"start_time": "2221-01-01T00:00:00.000-07:00"
}
}
]
}
}
},
{
"type": "STREAM",
"stream": {
"stream_state": {
"start_time": "2221-07-05"
},
"stream_descriptor": {
"name": "adsquads_stats_daily"
"name": "adsquads_stats_daily",
"namespace": null
},
"stream_state": {
"states": [
{
"partition": {
"adsquad_id": "ac6548b1-419e-4137-8320-e4e536766f72",
"parent_slice": {
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
}
},
"cursor": {
"start_time": "2221-01-01T00:00:00.000-07:00"
}
},
{
"partition": {
"id": "87f00f80-8ae6-44ac-ab63-2c976d43de64",
"parent_slice": {
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
}
},
"cursor": {
"start_time": "2221-01-01T00:00:00.000-07:00"
}
}
]
}
}
},
{
"type": "STREAM",
"stream": {
"stream_state": {
"start_time": "2221-07-05"
},
"stream_descriptor": {
"name": "campaigns_stats_daily"
"name": "campaigns_stats_daily",
"namespace": null
},
"stream_state": {
"states": [
{
"partition": {
"campaign_id": "3369834f-5bc0-47bd-a4e9-ee48d424d90c",
"parent_slice": {
"adaccount_id": "04214c00-3aa5-4123-b5c8-363c32c40e42",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
}
},
"cursor": {
"start_time": "2221-01-01T00:00:00.000-07:00"
}
},
{
"partition": {
"id": "d180d36e-1212-479b-84a5-8b0663ceaf82",
"parent_slice": {
"adaccount_id": "e4cd371b-8de8-4011-a8d2-860fe77c09e1",
"parent_slice": {
"organization_id": "7f064d90-52a1-42db-b25b-7539e663e926",
"parent_slice": {}
}
}
},
"cursor": {
"start_time": "2221-01-01T00:00:00.000-07:00"
}
}
]
}
}
}

View File

@@ -0,0 +1,60 @@
{
"streams": [
{
"stream": {
"name": "adaccounts_stats_hourly",
"json_schema": {},
"supported_sync_modes": ["full_refresh", "incremental"],
"source_defined_cursor": true,
"default_cursor_field": ["start_time"],
"source_defined_primary_key": [["id"], ["granularity"], ["start_time"]]
},
"sync_mode": "incremental",
"cursor_field": ["start_time"],
"primary_key": [["id"], ["granularity"], ["start_time"]],
"destination_sync_mode": "append"
},
{
"stream": {
"name": "ads_stats_hourly",
"json_schema": {},
"supported_sync_modes": ["full_refresh", "incremental"],
"source_defined_cursor": true,
"default_cursor_field": ["start_time"],
"source_defined_primary_key": [["id"], ["granularity"], ["start_time"]]
},
"sync_mode": "incremental",
"cursor_field": ["start_time"],
"primary_key": [["id"], ["granularity"], ["start_time"]],
"destination_sync_mode": "append"
},
{
"stream": {
"name": "adsquads_stats_hourly",
"json_schema": {},
"supported_sync_modes": ["full_refresh", "incremental"],
"source_defined_cursor": true,
"default_cursor_field": ["start_time"],
"source_defined_primary_key": [["id"], ["granularity"], ["start_time"]]
},
"sync_mode": "incremental",
"cursor_field": ["start_time"],
"primary_key": [["id"], ["granularity"], ["start_time"]],
"destination_sync_mode": "append"
},
{
"stream": {
"name": "campaigns_stats_hourly",
"json_schema": {},
"supported_sync_modes": ["full_refresh", "incremental"],
"source_defined_cursor": true,
"default_cursor_field": ["start_time"],
"source_defined_primary_key": [["id"], ["granularity"], ["start_time"]]
},
"sync_mode": "incremental",
"cursor_field": ["start_time"],
"destination_sync_mode": "append",
"primary_key": [["id"], ["granularity"], ["start_time"]]
}
]
}

View File

@@ -22,4 +22,4 @@
{"stream": "adsquads_stats_hourly", "data": {"start_time": "2024-05-14T23:00:00.000-07:00", "end_time": "2024-05-15T00:00:00.000-07:00", "id": "87f00f80-8ae6-44ac-ab63-2c976d43de64", "type": "AD_SQUAD", "granularity": "HOUR", "android_installs": 0, "attachment_avg_view_time_millis": 0, "attachment_impressions": 0, "attachment_quartile_1": 0, "attachment_quartile_2": 0, "attachment_quartile_3": 0, "attachment_total_view_time_millis": 0, "attachment_view_completion": 0, "avg_screen_time_millis": 0, "avg_view_time_millis": 0, "impressions": 0, "ios_installs": 0, "quartile_1": 0, "quartile_2": 0, "quartile_3": 0, "screen_time_millis": 0, "swipe_up_percent": 0.0, "swipes": 0, "total_installs": 0, "video_views": 0, "video_views_time_based": 0, "video_views_15s": 0, "view_completion": 0, "view_time_millis": 0, "paid_impressions": 0, "earned_impressions": 0, "total_impressions": 0, "play_time_millis": 0, "shares": 0, "saves": 0, "native_leads": 0, "conversion_purchases": 0, "conversion_purchases_value": 0, "conversion_save": 0, "conversion_start_checkout": 0, "conversion_add_cart": 0, "conversion_view_content": 0, "conversion_add_billing": 0, "conversion_searches": 0, "conversion_level_completes": 0, "conversion_app_opens": 0, "conversion_page_views": 0, "conversion_subscribe": 0, "conversion_ad_click": 0, "conversion_ad_view": 0, "conversion_complete_tutorial": 0, "conversion_invite": 0, "conversion_login": 0, "conversion_share": 0, "conversion_reserve": 0, "conversion_achievement_unlocked": 0, "conversion_add_to_wishlist": 0, "conversion_spend_credits": 0, "conversion_rate": 0, "conversion_start_trial": 0, "conversion_list_view": 0, "custom_event_1": 0, "custom_event_2": 0, "custom_event_3": 0, "custom_event_4": 0, "custom_event_5": 0, "story_opens": 0, "story_completes": 0}, "emitted_at": 1718737703937}
{"stream": "adsquads_stats_hourly", "data": {"start_time": "2024-05-15T00:00:00.000-07:00", "end_time": "2024-05-15T01:00:00.000-07:00", "id": "87f00f80-8ae6-44ac-ab63-2c976d43de64", "type": "AD_SQUAD", "granularity": "HOUR", "android_installs": 0, "attachment_avg_view_time_millis": 0, "attachment_impressions": 0, "attachment_quartile_1": 0, "attachment_quartile_2": 0, "attachment_quartile_3": 0, "attachment_total_view_time_millis": 0, "attachment_view_completion": 0, "avg_screen_time_millis": 0, "avg_view_time_millis": 0, "impressions": 0, "ios_installs": 0, "quartile_1": 0, "quartile_2": 0, "quartile_3": 0, "screen_time_millis": 0, "swipe_up_percent": 0.0, "swipes": 0, "total_installs": 0, "video_views": 0, "video_views_time_based": 0, "video_views_15s": 0, "view_completion": 0, "view_time_millis": 0, "paid_impressions": 0, "earned_impressions": 0, "total_impressions": 0, "play_time_millis": 0, "shares": 0, "saves": 0, "native_leads": 0, "conversion_purchases": 0, "conversion_purchases_value": 0, "conversion_save": 0, "conversion_start_checkout": 0, "conversion_add_cart": 0, "conversion_view_content": 0, "conversion_add_billing": 0, "conversion_searches": 0, "conversion_level_completes": 0, "conversion_app_opens": 0, "conversion_page_views": 0, "conversion_subscribe": 0, "conversion_ad_click": 0, "conversion_ad_view": 0, "conversion_complete_tutorial": 0, "conversion_invite": 0, "conversion_login": 0, "conversion_share": 0, "conversion_reserve": 0, "conversion_achievement_unlocked": 0, "conversion_add_to_wishlist": 0, "conversion_spend_credits": 0, "conversion_rate": 0, "conversion_start_trial": 0, "conversion_list_view": 0, "custom_event_1": 0, "custom_event_2": 0, "custom_event_3": 0, "custom_event_4": 0, "custom_event_5": 0, "story_opens": 0, "story_completes": 0}, "emitted_at": 1718737704063}
{"stream": "campaigns_stats_hourly", "data": {"start_time": "2024-05-14T21:00:00.000-07:00", "end_time": "2024-05-14T22:00:00.000-07:00", "id": "d180d36e-1212-479b-84a5-8b0663ceaf82", "type": "CAMPAIGN", "granularity": "HOUR", "android_installs": 0, "attachment_avg_view_time_millis": 0, "attachment_impressions": 0, "attachment_quartile_1": 0, "attachment_quartile_2": 0, "attachment_quartile_3": 0, "attachment_total_view_time_millis": 0, "attachment_view_completion": 0, "avg_screen_time_millis": 0, "avg_view_time_millis": 0, "impressions": 0, "ios_installs": 0, "quartile_1": 0, "quartile_2": 0, "quartile_3": 0, "screen_time_millis": 0, "swipe_up_percent": 0.0, "swipes": 0, "total_installs": 0, "video_views": 0, "video_views_time_based": 0, "video_views_15s": 0, "view_completion": 0, "view_time_millis": 0, "paid_impressions": 0, "earned_impressions": 0, "total_impressions": 0, "play_time_millis": 0, "shares": 0, "saves": 0, "native_leads": 0, "conversion_purchases": 0, "conversion_purchases_value": 0, "conversion_save": 0, "conversion_start_checkout": 0, "conversion_add_cart": 0, "conversion_view_content": 0, "conversion_add_billing": 0, "conversion_searches": 0, "conversion_level_completes": 0, "conversion_app_opens": 0, "conversion_page_views": 0, "conversion_subscribe": 0, "conversion_ad_click": 0, "conversion_ad_view": 0, "conversion_complete_tutorial": 0, "conversion_invite": 0, "conversion_login": 0, "conversion_share": 0, "conversion_reserve": 0, "conversion_achievement_unlocked": 0, "conversion_add_to_wishlist": 0, "conversion_spend_credits": 0, "conversion_rate": 0, "conversion_start_trial": 0, "conversion_list_view": 0, "custom_event_1": 0, "custom_event_2": 0, "custom_event_3": 0, "custom_event_4": 0, "custom_event_5": 0, "story_opens": 0, "story_completes": 0}, "emitted_at": 1718737739971}
{"stream": "campaigns_stats_hourly", "data": {"start_time": "2024-05-14T22:00:00.000-07:00", "end_time": "2024-05-14T23:00:00.000-07:00", "id": "d180d36e-1212-479b-84a5-8b0663ceaf82", "type": "CAMPAIGN", "granularity": "HOUR", "android_installs": 0, "attachment_avg_view_time_millis": 0, "attachment_impressions": 0, "attachment_quartile_1": 0, "attachment_quartile_2": 0, "attachment_quartile_3": 0, "attachment_total_view_time_millis": 0, "attachment_view_completion": 0, "avg_screen_time_millis": 0, "avg_view_time_millis": 0, "impressions": 0, "ios_installs": 0, "quartile_1": 0, "quartile_2": 0, "quartile_3": 0, "screen_time_millis": 0, "swipe_up_percent": 0.0, "swipes": 0, "total_installs": 0, "video_views": 0, "video_views_time_based": 0, "video_views_15s": 0, "view_completion": 0, "view_time_millis": 0, "paid_impressions": 0, "earned_impressions": 0, "total_impressions": 0, "play_time_millis": 0, "shares": 0, "saves": 0, "native_leads": 0, "conversion_purchases": 0, "conversion_purchases_value": 0, "conversion_save": 0, "conversion_start_checkout": 0, "conversion_add_cart": 0, "conversion_view_content": 0, "conversion_add_billing": 0, "conversion_searches": 0, "conversion_level_completes": 0, "conversion_app_opens": 0, "conversion_page_views": 0, "conversion_subscribe": 0, "conversion_ad_click": 0, "conversion_ad_view": 0, "conversion_complete_tutorial": 0, "conversion_invite": 0, "conversion_login": 0, "conversion_share": 0, "conversion_reserve": 0, "conversion_achievement_unlocked": 0, "conversion_add_to_wishlist": 0, "conversion_spend_credits": 0, "conversion_rate": 0, "conversion_start_trial": 0, "conversion_list_view": 0, "custom_event_1": 0, "custom_event_2": 0, "custom_event_3": 0, "custom_event_4": 0, "custom_event_5": 0, "story_opens": 0, "story_completes": 0}, "emitted_at": 1718737740086}
{"stream": "campaigns_stats_hourly", "data": {"start_time": "2024-05-14T22:00:00.000-07:00", "end_time": "2024-05-14T23:00:00.000-07:00", "id": "d180d36e-1212-479b-84a5-8b0663ceaf82", "type": "CAMPAIGN", "granularity": "HOUR", "android_installs": 0, "attachment_avg_view_time_millis": 0, "attachment_impressions": 0, "attachment_quartile_1": 0, "attachment_quartile_2": 0, "attachment_quartile_3": 0, "attachment_total_view_time_millis": 0, "attachment_view_completion": 0, "avg_screen_time_millis": 0, "avg_view_time_millis": 0, "impressions": 0, "ios_installs": 0, "quartile_1": 0, "quartile_2": 0, "quartile_3": 0, "screen_time_millis": 0, "swipe_up_percent": 0.0, "swipes": 0, "total_installs": 0, "video_views": 0, "video_views_time_based": 0, "video_views_15s": 0, "view_completion": 0, "view_time_millis": 0, "paid_impressions": 0, "earned_impressions": 0, "total_impressions": 0, "play_time_millis": 0, "shares": 0, "saves": 0, "native_leads": 0, "conversion_purchases": 0, "conversion_purchases_value": 0, "conversion_save": 0, "conversion_start_checkout": 0, "conversion_add_cart": 0, "conversion_view_content": 0, "conversion_add_billing": 0, "conversion_searches": 0, "conversion_level_completes": 0, "conversion_app_opens": 0, "conversion_page_views": 0, "conversion_subscribe": 0, "conversion_ad_click": 0, "conversion_ad_view": 0, "conversion_complete_tutorial": 0, "conversion_invite": 0, "conversion_login": 0, "conversion_share": 0, "conversion_reserve": 0, "conversion_achievement_unlocked": 0, "conversion_add_to_wishlist": 0, "conversion_spend_credits": 0, "conversion_rate": 0, "conversion_start_trial": 0, "conversion_list_view": 0, "custom_event_1": 0, "custom_event_2": 0, "custom_event_3": 0, "custom_event_4": 0, "custom_event_5": 0, "story_opens": 0, "story_completes": 0}, "emitted_at": 1718737740086}

View File

@@ -1,5 +1,4 @@
{
"documentationUrl": "https://docs.airbyte.com/integrations/sources/snapchat-marketing",
"connectionSpecification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Snapchat Marketing Spec",
@@ -74,7 +73,10 @@
},
"advanced_auth": {
"auth_flow_type": "oauth2.0",
"predicate_key": null,
"predicate_value": null,
"oauth_config_specification": {
"oauth_user_input_from_connector_config_specification": null,
"complete_oauth_output_specification": {
"type": "object",
"properties": {

View File

@@ -8,7 +8,7 @@ data:
connectorSubtype: api
connectorType: source
definitionId: 200330b2-ea62-4d11-ac6d-cfe3e3f8ab2b
dockerImageTag: 0.6.2
dockerImageTag: 1.0.0
dockerRepository: airbyte/source-snapchat-marketing
githubIssueLabel: source-snapchat-marketing
icon: snapchat.svg
@@ -25,10 +25,42 @@ data:
oss:
enabled: true
releaseStage: generally_available
releases:
breakingChanges:
1.0.0:
message: >-
The source Snapchat Marketing connector is being migrated from the Python CDK to our declarative low-code CDK.
Due to changes to the incremental stream state, this migration constitutes a breaking change. Additionally,
added incremental functionality to organizations. After updating, please reset your source before resuming syncs.
For more information, see our migration documentation for source Snapchat Marketing.
upgradeDeadline: "2024-07-16"
scopedImpact:
- scopeType: stream
impactedScopes:
- "organizations"
- "adaccounts"
- "creatives"
- "ads"
- "adsquads"
- "segments"
- "media"
- "campaigns"
- "adaccounts_stats_hourly"
- "adaccounts_stats_daily"
- "adaccounts_stats_lifetime"
- "ads_stats_hourly"
- "ads_stats_daily"
- "ads_stats_lifetime"
- "adsquads_stats_hourly"
- "adsquads_stats_daily"
- "adsquads_stats_lifetime"
- "campaigns_stats_hourly"
- "campaigns_stats_daily"
- "campaigns_stats_lifetime"
documentationUrl: https://docs.airbyte.com/integrations/sources/snapchat-marketing
tags:
- language:python
- cdk:python
- cdk:low-code
ab_internal:
sl: 200
ql: 400

View File

@@ -1,14 +1,14 @@
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
[[package]]
name = "airbyte-cdk"
version = "0.90.0"
version = "1.8.0"
description = "A framework for writing Airbyte Connectors."
optional = false
python-versions = "<4.0,>=3.9"
files = [
{file = "airbyte_cdk-0.90.0-py3-none-any.whl", hash = "sha256:bd0aa5843cdc4901f2e482f0e86695ca4e6db83b65c5017799255dd20535cf56"},
{file = "airbyte_cdk-0.90.0.tar.gz", hash = "sha256:25cefc010718bada5cce3f87e7ae93068630732c0d34ce5145f8ddf7457d4d3c"},
{file = "airbyte_cdk-1.8.0-py3-none-any.whl", hash = "sha256:ca23d7877005fe87ffc4a3a3de29ee55eed625d874eb59b49664b156f9ae9ee2"},
{file = "airbyte_cdk-1.8.0.tar.gz", hash = "sha256:ac82fbfd6b650b7ed015900748e30fdd2a4c574caa54d1bcc03cb584a17f1533"},
]
[package.dependencies]
@@ -17,7 +17,7 @@ backoff = "*"
cachetools = "*"
cryptography = ">=42.0.5,<43.0.0"
Deprecated = ">=1.2,<1.3"
dpath = ">=2.0.1,<2.1.0"
dpath = ">=2.1.6,<3.0.0"
genson = "1.2.2"
isodate = ">=0.6.1,<0.7.0"
Jinja2 = ">=3.1.2,<3.2.0"
@@ -42,13 +42,13 @@ vector-db-based = ["cohere (==4.21)", "langchain (==0.1.16)", "openai[embeddings
[[package]]
name = "airbyte-protocol-models"
version = "0.11.0"
version = "0.12.2"
description = "Declares the Airbyte Protocol."
optional = false
python-versions = ">=3.8"
files = [
{file = "airbyte_protocol_models-0.11.0-py3-none-any.whl", hash = "sha256:2157757c1af8c13e471ab6a0304fd2f9a2a6af8cc9173937be1348a9553f7c32"},
{file = "airbyte_protocol_models-0.11.0.tar.gz", hash = "sha256:1c7e46251b0d5a292b4aa382df24f415ac2a2a2b4719361b3c0f76368a043c23"},
{file = "airbyte_protocol_models-0.12.2-py3-none-any.whl", hash = "sha256:1780db5b26285865b858d26502933def8e11919c9436ccf7b8b9cb0170b07c2a"},
{file = "airbyte_protocol_models-0.12.2.tar.gz", hash = "sha256:b7c4d9a7c32c0691601c2b9416af090a858e126666e2c8c880d7a1798eb519f0"},
]
[package.dependencies]
@@ -143,13 +143,13 @@ ujson = ["ujson (>=5.7.0)"]
[[package]]
name = "certifi"
version = "2024.2.2"
version = "2024.6.2"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.6"
files = [
{file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"},
{file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"},
{file = "certifi-2024.6.2-py3-none-any.whl", hash = "sha256:ddc6c8ce995e6987e7faf5e3f1b02b302836a0e5d98ece18392cb1a36c72ad56"},
{file = "certifi-2024.6.2.tar.gz", hash = "sha256:3cd43f1c6fa7dedc5899d69d3ad0398fd018ad1a17fba83ddaf78aa46c747516"},
]
[[package]]
@@ -328,43 +328,43 @@ files = [
[[package]]
name = "cryptography"
version = "42.0.7"
version = "42.0.8"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
optional = false
python-versions = ">=3.7"
files = [
{file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"},
{file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"},
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"},
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"},
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"},
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"},
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"},
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"},
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"},
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"},
{file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"},
{file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"},
{file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"},
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"},
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"},
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"},
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"},
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"},
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"},
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"},
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"},
{file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"},
{file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"},
{file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"},
{file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"},
{file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"},
{file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"},
{file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"},
{file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"},
{file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"},
{file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"},
{file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"},
{file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"},
{file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"},
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"},
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"},
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"},
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"},
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"},
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"},
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"},
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"},
{file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"},
{file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"},
{file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"},
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"},
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"},
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"},
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"},
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"},
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"},
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"},
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"},
{file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"},
{file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"},
{file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"},
{file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"},
{file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"},
{file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"},
{file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"},
{file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"},
{file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"},
{file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"},
{file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"},
]
[package.dependencies]
@@ -399,13 +399,13 @@ dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"]
[[package]]
name = "dpath"
version = "2.0.8"
version = "2.2.0"
description = "Filesystem-like pathing and searching for dictionaries"
optional = false
python-versions = ">=3.7"
files = [
{file = "dpath-2.0.8-py3-none-any.whl", hash = "sha256:f92f595214dd93a00558d75d4b858beee519f4cffca87f02616ad6cd013f3436"},
{file = "dpath-2.0.8.tar.gz", hash = "sha256:a3440157ebe80d0a3ad794f1b61c571bef125214800ffdb9afc9424e8250fe9b"},
{file = "dpath-2.2.0-py3-none-any.whl", hash = "sha256:b330a375ded0a0d2ed404440f6c6a715deae5313af40bbb01c8a41d891900576"},
{file = "dpath-2.2.0.tar.gz", hash = "sha256:34f7e630dc55ea3f219e555726f5da4b4b25f2200319c8e6902c394258dd6a3e"},
]
[[package]]
@@ -501,13 +501,13 @@ jsonpointer = ">=1.9"
[[package]]
name = "jsonpointer"
version = "2.4"
version = "3.0.0"
description = "Identify specific nodes in a JSON document (RFC 6901)"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*"
python-versions = ">=3.7"
files = [
{file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"},
{file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"},
{file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"},
{file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"},
]
[[package]]
@@ -566,13 +566,13 @@ extended-testing = ["jinja2 (>=3,<4)"]
[[package]]
name = "langsmith"
version = "0.1.60"
version = "0.1.81"
description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
optional = false
python-versions = "<4.0,>=3.8.1"
files = [
{file = "langsmith-0.1.60-py3-none-any.whl", hash = "sha256:3c3520ea473de0a984237b3e9d638fdf23ef3acc5aec89a42e693225e72d6120"},
{file = "langsmith-0.1.60.tar.gz", hash = "sha256:6a145b5454437f9e0f81525f23c4dcdbb8c07b1c91553b8f697456c418d6a599"},
{file = "langsmith-0.1.81-py3-none-any.whl", hash = "sha256:3251d823225eef23ee541980b9d9e506367eabbb7f985a086b5d09e8f78ba7e9"},
{file = "langsmith-0.1.81.tar.gz", hash = "sha256:585ef3a2251380bd2843a664c9a28da4a7d28432e3ee8bcebf291ffb8e1f0af0"},
]
[package.dependencies]
@@ -651,57 +651,57 @@ files = [
[[package]]
name = "orjson"
version = "3.10.3"
version = "3.10.5"
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
optional = false
python-versions = ">=3.8"
files = [
{file = "orjson-3.10.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9fb6c3f9f5490a3eb4ddd46fc1b6eadb0d6fc16fb3f07320149c3286a1409dd8"},
{file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:252124b198662eee80428f1af8c63f7ff077c88723fe206a25df8dc57a57b1fa"},
{file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f3e87733823089a338ef9bbf363ef4de45e5c599a9bf50a7a9b82e86d0228da"},
{file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8334c0d87103bb9fbbe59b78129f1f40d1d1e8355bbed2ca71853af15fa4ed3"},
{file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1952c03439e4dce23482ac846e7961f9d4ec62086eb98ae76d97bd41d72644d7"},
{file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0403ed9c706dcd2809f1600ed18f4aae50be263bd7112e54b50e2c2bc3ebd6d"},
{file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:382e52aa4270a037d41f325e7d1dfa395b7de0c367800b6f337d8157367bf3a7"},
{file = "orjson-3.10.3-cp310-none-win32.whl", hash = "sha256:be2aab54313752c04f2cbaab4515291ef5af8c2256ce22abc007f89f42f49109"},
{file = "orjson-3.10.3-cp310-none-win_amd64.whl", hash = "sha256:416b195f78ae461601893f482287cee1e3059ec49b4f99479aedf22a20b1098b"},
{file = "orjson-3.10.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:73100d9abbbe730331f2242c1fc0bcb46a3ea3b4ae3348847e5a141265479700"},
{file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a12eee96e3ab828dbfcb4d5a0023aa971b27143a1d35dc214c176fdfb29b3"},
{file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520de5e2ef0b4ae546bea25129d6c7c74edb43fc6cf5213f511a927f2b28148b"},
{file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccaa0a401fc02e8828a5bedfd80f8cd389d24f65e5ca3954d72c6582495b4bcf"},
{file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7bc9e8bc11bac40f905640acd41cbeaa87209e7e1f57ade386da658092dc16"},
{file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3582b34b70543a1ed6944aca75e219e1192661a63da4d039d088a09c67543b08"},
{file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c23dfa91481de880890d17aa7b91d586a4746a4c2aa9a145bebdbaf233768d5"},
{file = "orjson-3.10.3-cp311-none-win32.whl", hash = "sha256:1770e2a0eae728b050705206d84eda8b074b65ee835e7f85c919f5705b006c9b"},
{file = "orjson-3.10.3-cp311-none-win_amd64.whl", hash = "sha256:93433b3c1f852660eb5abdc1f4dd0ced2be031ba30900433223b28ee0140cde5"},
{file = "orjson-3.10.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a39aa73e53bec8d410875683bfa3a8edf61e5a1c7bb4014f65f81d36467ea098"},
{file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0943a96b3fa09bee1afdfccc2cb236c9c64715afa375b2af296c73d91c23eab2"},
{file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e852baafceff8da3c9defae29414cc8513a1586ad93e45f27b89a639c68e8176"},
{file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18566beb5acd76f3769c1d1a7ec06cdb81edc4d55d2765fb677e3eaa10fa99e0"},
{file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd2218d5a3aa43060efe649ec564ebedec8ce6ae0a43654b81376216d5ebd42"},
{file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cf20465e74c6e17a104ecf01bf8cd3b7b252565b4ccee4548f18b012ff2f8069"},
{file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7f67aa7f983c4345eeda16054a4677289011a478ca947cd69c0a86ea45e534"},
{file = "orjson-3.10.3-cp312-none-win32.whl", hash = "sha256:17e0713fc159abc261eea0f4feda611d32eabc35708b74bef6ad44f6c78d5ea0"},
{file = "orjson-3.10.3-cp312-none-win_amd64.whl", hash = "sha256:4c895383b1ec42b017dd2c75ae8a5b862fc489006afde06f14afbdd0309b2af0"},
{file = "orjson-3.10.3-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:be2719e5041e9fb76c8c2c06b9600fe8e8584e6980061ff88dcbc2691a16d20d"},
{file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0175a5798bdc878956099f5c54b9837cb62cfbf5d0b86ba6d77e43861bcec2"},
{file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:978be58a68ade24f1af7758626806e13cff7748a677faf95fbb298359aa1e20d"},
{file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16bda83b5c61586f6f788333d3cf3ed19015e3b9019188c56983b5a299210eb5"},
{file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ad1f26bea425041e0a1adad34630c4825a9e3adec49079b1fb6ac8d36f8b754"},
{file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9e253498bee561fe85d6325ba55ff2ff08fb5e7184cd6a4d7754133bd19c9195"},
{file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a62f9968bab8a676a164263e485f30a0b748255ee2f4ae49a0224be95f4532b"},
{file = "orjson-3.10.3-cp38-none-win32.whl", hash = "sha256:8d0b84403d287d4bfa9bf7d1dc298d5c1c5d9f444f3737929a66f2fe4fb8f134"},
{file = "orjson-3.10.3-cp38-none-win_amd64.whl", hash = "sha256:8bc7a4df90da5d535e18157220d7915780d07198b54f4de0110eca6b6c11e290"},
{file = "orjson-3.10.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9059d15c30e675a58fdcd6f95465c1522b8426e092de9fff20edebfdc15e1cb0"},
{file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d40c7f7938c9c2b934b297412c067936d0b54e4b8ab916fd1a9eb8f54c02294"},
{file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a654ec1de8fdaae1d80d55cee65893cb06494e124681ab335218be6a0691e7"},
{file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831c6ef73f9aa53c5f40ae8f949ff7681b38eaddb6904aab89dca4d85099cb78"},
{file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b880d7e34542db89f48d14ddecbd26f06838b12427d5a25d71baceb5ba119d"},
{file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e5e176c994ce4bd434d7aafb9ecc893c15f347d3d2bbd8e7ce0b63071c52e25"},
{file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b69a58a37dab856491bf2d3bbf259775fdce262b727f96aafbda359cb1d114d8"},
{file = "orjson-3.10.3-cp39-none-win32.whl", hash = "sha256:b8d4d1a6868cde356f1402c8faeb50d62cee765a1f7ffcfd6de732ab0581e063"},
{file = "orjson-3.10.3-cp39-none-win_amd64.whl", hash = "sha256:5102f50c5fc46d94f2033fe00d392588564378260d64377aec702f21a7a22912"},
{file = "orjson-3.10.3.tar.gz", hash = "sha256:2b166507acae7ba2f7c315dcf185a9111ad5e992ac81f2d507aac39193c2c818"},
{file = "orjson-3.10.5-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:545d493c1f560d5ccfc134803ceb8955a14c3fcb47bbb4b2fee0232646d0b932"},
{file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4324929c2dd917598212bfd554757feca3e5e0fa60da08be11b4aa8b90013c1"},
{file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c13ca5e2ddded0ce6a927ea5a9f27cae77eee4c75547b4297252cb20c4d30e6"},
{file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b6c8e30adfa52c025f042a87f450a6b9ea29649d828e0fec4858ed5e6caecf63"},
{file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:338fd4f071b242f26e9ca802f443edc588fa4ab60bfa81f38beaedf42eda226c"},
{file = "orjson-3.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6970ed7a3126cfed873c5d21ece1cd5d6f83ca6c9afb71bbae21a0b034588d96"},
{file = "orjson-3.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:235dadefb793ad12f7fa11e98a480db1f7c6469ff9e3da5e73c7809c700d746b"},
{file = "orjson-3.10.5-cp310-none-win32.whl", hash = "sha256:be79e2393679eda6a590638abda16d167754393f5d0850dcbca2d0c3735cebe2"},
{file = "orjson-3.10.5-cp310-none-win_amd64.whl", hash = "sha256:c4a65310ccb5c9910c47b078ba78e2787cb3878cdded1702ac3d0da71ddc5228"},
{file = "orjson-3.10.5-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:cdf7365063e80899ae3a697def1277c17a7df7ccfc979990a403dfe77bb54d40"},
{file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b68742c469745d0e6ca5724506858f75e2f1e5b59a4315861f9e2b1df77775a"},
{file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7d10cc1b594951522e35a3463da19e899abe6ca95f3c84c69e9e901e0bd93d38"},
{file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dcbe82b35d1ac43b0d84072408330fd3295c2896973112d495e7234f7e3da2e1"},
{file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c0eb7e0c75e1e486c7563fe231b40fdd658a035ae125c6ba651ca3b07936f5"},
{file = "orjson-3.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:53ed1c879b10de56f35daf06dbc4a0d9a5db98f6ee853c2dbd3ee9d13e6f302f"},
{file = "orjson-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:099e81a5975237fda3100f918839af95f42f981447ba8f47adb7b6a3cdb078fa"},
{file = "orjson-3.10.5-cp311-none-win32.whl", hash = "sha256:1146bf85ea37ac421594107195db8bc77104f74bc83e8ee21a2e58596bfb2f04"},
{file = "orjson-3.10.5-cp311-none-win_amd64.whl", hash = "sha256:36a10f43c5f3a55c2f680efe07aa93ef4a342d2960dd2b1b7ea2dd764fe4a37c"},
{file = "orjson-3.10.5-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:68f85ecae7af14a585a563ac741b0547a3f291de81cd1e20903e79f25170458f"},
{file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28afa96f496474ce60d3340fe8d9a263aa93ea01201cd2bad844c45cd21f5268"},
{file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cd684927af3e11b6e754df80b9ffafd9fb6adcaa9d3e8fdd5891be5a5cad51e"},
{file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d21b9983da032505f7050795e98b5d9eee0df903258951566ecc358f6696969"},
{file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ad1de7fef79736dde8c3554e75361ec351158a906d747bd901a52a5c9c8d24b"},
{file = "orjson-3.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d97531cdfe9bdd76d492e69800afd97e5930cb0da6a825646667b2c6c6c0211"},
{file = "orjson-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d69858c32f09c3e1ce44b617b3ebba1aba030e777000ebdf72b0d8e365d0b2b3"},
{file = "orjson-3.10.5-cp312-none-win32.whl", hash = "sha256:64c9cc089f127e5875901ac05e5c25aa13cfa5dbbbd9602bda51e5c611d6e3e2"},
{file = "orjson-3.10.5-cp312-none-win_amd64.whl", hash = "sha256:b2efbd67feff8c1f7728937c0d7f6ca8c25ec81373dc8db4ef394c1d93d13dc5"},
{file = "orjson-3.10.5-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:03b565c3b93f5d6e001db48b747d31ea3819b89abf041ee10ac6988886d18e01"},
{file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:584c902ec19ab7928fd5add1783c909094cc53f31ac7acfada817b0847975f26"},
{file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a35455cc0b0b3a1eaf67224035f5388591ec72b9b6136d66b49a553ce9eb1e6"},
{file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1670fe88b116c2745a3a30b0f099b699a02bb3482c2591514baf5433819e4f4d"},
{file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185c394ef45b18b9a7d8e8f333606e2e8194a50c6e3c664215aae8cf42c5385e"},
{file = "orjson-3.10.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ca0b3a94ac8d3886c9581b9f9de3ce858263865fdaa383fbc31c310b9eac07c9"},
{file = "orjson-3.10.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dfc91d4720d48e2a709e9c368d5125b4b5899dced34b5400c3837dadc7d6271b"},
{file = "orjson-3.10.5-cp38-none-win32.whl", hash = "sha256:c05f16701ab2a4ca146d0bca950af254cb7c02f3c01fca8efbbad82d23b3d9d4"},
{file = "orjson-3.10.5-cp38-none-win_amd64.whl", hash = "sha256:8a11d459338f96a9aa7f232ba95679fc0c7cedbd1b990d736467894210205c09"},
{file = "orjson-3.10.5-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:85c89131d7b3218db1b24c4abecea92fd6c7f9fab87441cfc342d3acc725d807"},
{file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb66215277a230c456f9038d5e2d84778141643207f85336ef8d2a9da26bd7ca"},
{file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:51bbcdea96cdefa4a9b4461e690c75ad4e33796530d182bdd5c38980202c134a"},
{file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbead71dbe65f959b7bd8cf91e0e11d5338033eba34c114f69078d59827ee139"},
{file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5df58d206e78c40da118a8c14fc189207fffdcb1f21b3b4c9c0c18e839b5a214"},
{file = "orjson-3.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c4057c3b511bb8aef605616bd3f1f002a697c7e4da6adf095ca5b84c0fd43595"},
{file = "orjson-3.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b39e006b00c57125ab974362e740c14a0c6a66ff695bff44615dcf4a70ce2b86"},
{file = "orjson-3.10.5-cp39-none-win32.whl", hash = "sha256:eded5138cc565a9d618e111c6d5c2547bbdd951114eb822f7f6309e04db0fb47"},
{file = "orjson-3.10.5-cp39-none-win_amd64.whl", hash = "sha256:cc28e90a7cae7fcba2493953cff61da5a52950e78dc2dacfe931a317ee3d8de7"},
{file = "orjson-3.10.5.tar.gz", hash = "sha256:7a5baef8a4284405d96c90c7c62b755e9ef1ada84c2406c24a9ebec86b89f46d"},
]
[[package]]
@@ -804,47 +804,47 @@ files = [
[[package]]
name = "pydantic"
version = "1.10.15"
version = "1.10.16"
description = "Data validation and settings management using python type hints"
optional = false
python-versions = ">=3.7"
files = [
{file = "pydantic-1.10.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:22ed12ee588b1df028a2aa5d66f07bf8f8b4c8579c2e96d5a9c1f96b77f3bb55"},
{file = "pydantic-1.10.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:75279d3cac98186b6ebc2597b06bcbc7244744f6b0b44a23e4ef01e5683cc0d2"},
{file = "pydantic-1.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50f1666a9940d3d68683c9d96e39640f709d7a72ff8702987dab1761036206bb"},
{file = "pydantic-1.10.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82790d4753ee5d00739d6cb5cf56bceb186d9d6ce134aca3ba7befb1eedbc2c8"},
{file = "pydantic-1.10.15-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d207d5b87f6cbefbdb1198154292faee8017d7495a54ae58db06762004500d00"},
{file = "pydantic-1.10.15-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e49db944fad339b2ccb80128ffd3f8af076f9f287197a480bf1e4ca053a866f0"},
{file = "pydantic-1.10.15-cp310-cp310-win_amd64.whl", hash = "sha256:d3b5c4cbd0c9cb61bbbb19ce335e1f8ab87a811f6d589ed52b0254cf585d709c"},
{file = "pydantic-1.10.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c3d5731a120752248844676bf92f25a12f6e45425e63ce22e0849297a093b5b0"},
{file = "pydantic-1.10.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c365ad9c394f9eeffcb30a82f4246c0006417f03a7c0f8315d6211f25f7cb654"},
{file = "pydantic-1.10.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3287e1614393119c67bd4404f46e33ae3be3ed4cd10360b48d0a4459f420c6a3"},
{file = "pydantic-1.10.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be51dd2c8596b25fe43c0a4a59c2bee4f18d88efb8031188f9e7ddc6b469cf44"},
{file = "pydantic-1.10.15-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6a51a1dd4aa7b3f1317f65493a182d3cff708385327c1c82c81e4a9d6d65b2e4"},
{file = "pydantic-1.10.15-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4e316e54b5775d1eb59187f9290aeb38acf620e10f7fd2f776d97bb788199e53"},
{file = "pydantic-1.10.15-cp311-cp311-win_amd64.whl", hash = "sha256:0d142fa1b8f2f0ae11ddd5e3e317dcac060b951d605fda26ca9b234b92214986"},
{file = "pydantic-1.10.15-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7ea210336b891f5ea334f8fc9f8f862b87acd5d4a0cbc9e3e208e7aa1775dabf"},
{file = "pydantic-1.10.15-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3453685ccd7140715e05f2193d64030101eaad26076fad4e246c1cc97e1bb30d"},
{file = "pydantic-1.10.15-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bea1f03b8d4e8e86702c918ccfd5d947ac268f0f0cc6ed71782e4b09353b26f"},
{file = "pydantic-1.10.15-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:005655cabc29081de8243126e036f2065bd7ea5b9dff95fde6d2c642d39755de"},
{file = "pydantic-1.10.15-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:af9850d98fc21e5bc24ea9e35dd80a29faf6462c608728a110c0a30b595e58b7"},
{file = "pydantic-1.10.15-cp37-cp37m-win_amd64.whl", hash = "sha256:d31ee5b14a82c9afe2bd26aaa405293d4237d0591527d9129ce36e58f19f95c1"},
{file = "pydantic-1.10.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5e09c19df304b8123938dc3c53d3d3be6ec74b9d7d0d80f4f4b5432ae16c2022"},
{file = "pydantic-1.10.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7ac9237cd62947db00a0d16acf2f3e00d1ae9d3bd602b9c415f93e7a9fc10528"},
{file = "pydantic-1.10.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:584f2d4c98ffec420e02305cf675857bae03c9d617fcfdc34946b1160213a948"},
{file = "pydantic-1.10.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbc6989fad0c030bd70a0b6f626f98a862224bc2b1e36bfc531ea2facc0a340c"},
{file = "pydantic-1.10.15-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d573082c6ef99336f2cb5b667b781d2f776d4af311574fb53d908517ba523c22"},
{file = "pydantic-1.10.15-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6bd7030c9abc80134087d8b6e7aa957e43d35714daa116aced57269a445b8f7b"},
{file = "pydantic-1.10.15-cp38-cp38-win_amd64.whl", hash = "sha256:3350f527bb04138f8aff932dc828f154847fbdc7a1a44c240fbfff1b57f49a12"},
{file = "pydantic-1.10.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:51d405b42f1b86703555797270e4970a9f9bd7953f3990142e69d1037f9d9e51"},
{file = "pydantic-1.10.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a980a77c52723b0dc56640ced396b73a024d4b74f02bcb2d21dbbac1debbe9d0"},
{file = "pydantic-1.10.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67f1a1fb467d3f49e1708a3f632b11c69fccb4e748a325d5a491ddc7b5d22383"},
{file = "pydantic-1.10.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:676ed48f2c5bbad835f1a8ed8a6d44c1cd5a21121116d2ac40bd1cd3619746ed"},
{file = "pydantic-1.10.15-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:92229f73400b80c13afcd050687f4d7e88de9234d74b27e6728aa689abcf58cc"},
{file = "pydantic-1.10.15-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2746189100c646682eff0bce95efa7d2e203420d8e1c613dc0c6b4c1d9c1fde4"},
{file = "pydantic-1.10.15-cp39-cp39-win_amd64.whl", hash = "sha256:394f08750bd8eaad714718812e7fab615f873b3cdd0b9d84e76e51ef3b50b6b7"},
{file = "pydantic-1.10.15-py3-none-any.whl", hash = "sha256:28e552a060ba2740d0d2aabe35162652c1459a0b9069fe0db7f4ee0e18e74d58"},
{file = "pydantic-1.10.15.tar.gz", hash = "sha256:ca832e124eda231a60a041da4f013e3ff24949d94a01154b137fc2f2a43c3ffb"},
{file = "pydantic-1.10.16-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1a539ac40551b01a85e899829aa43ca8036707474af8d74b48be288d4d2d2846"},
{file = "pydantic-1.10.16-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a4fcc7b0b8038dbda2dda642cff024032dfae24a7960cc58e57a39eb1949b9b"},
{file = "pydantic-1.10.16-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4660dd697de1ae2d4305a85161312611f64d5360663a9ba026cd6ad9e3fe14c3"},
{file = "pydantic-1.10.16-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:900a787c574f903a97d0bf52a43ff3b6cf4fa0119674bcfc0e5fd1056d388ad9"},
{file = "pydantic-1.10.16-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d30192a63e6d3334c3f0c0506dd6ae9f1dce7b2f8845518915291393a5707a22"},
{file = "pydantic-1.10.16-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:16cf23ed599ca5ca937e37ba50ab114e6b5c387eb43a6cc533701605ad1be611"},
{file = "pydantic-1.10.16-cp310-cp310-win_amd64.whl", hash = "sha256:8d23111f41d1e19334edd51438fd57933f3eee7d9d2fa8cc3f5eda515a272055"},
{file = "pydantic-1.10.16-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef287b8d7fc0e86a8bd1f902c61aff6ba9479c50563242fe88ba39692e98e1e0"},
{file = "pydantic-1.10.16-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b9ded699bfd3b3912d796ff388b0c607e6d35d41053d37aaf8fd6082c660de9a"},
{file = "pydantic-1.10.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:daeb199814333e4426c5e86d7fb610f4e230289f28cab90eb4de27330bef93cf"},
{file = "pydantic-1.10.16-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5973843f1fa99ec6c3ac8d1a8698ac9340b35e45cca6c3e5beb5c3bd1ef15de6"},
{file = "pydantic-1.10.16-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6b8a7788a8528a558828fe4a48783cafdcf2612d13c491594a8161dc721629c"},
{file = "pydantic-1.10.16-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8abaecf54dacc9d991dda93c3b880d41092a8924cde94eeb811d7d9ab55df7d8"},
{file = "pydantic-1.10.16-cp311-cp311-win_amd64.whl", hash = "sha256:ddc7b682fbd23f051edc419dc6977e11dd2dbdd0cef9d05f0e15d1387862d230"},
{file = "pydantic-1.10.16-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:067c2b5539f7839653ad8c3d1fc2f1343338da8677b7b2172abf3cd3fdc8f719"},
{file = "pydantic-1.10.16-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d1fc943583c046ecad0ff5d6281ee571b64e11b5503d9595febdce54f38b290"},
{file = "pydantic-1.10.16-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18548b30ccebe71d380b0886cc44ea5d80afbcc155e3518792f13677ad06097d"},
{file = "pydantic-1.10.16-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4e92292f9580fc5ea517618580fac24e9f6dc5657196e977c194a8e50e14f5a9"},
{file = "pydantic-1.10.16-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5da8bc4bb4f85b8c97cc7f11141fddbbd29eb25e843672e5807e19cc3d7c1b7f"},
{file = "pydantic-1.10.16-cp37-cp37m-win_amd64.whl", hash = "sha256:a04ee1ea34172b87707a6ecfcdb120d7656892206b7c4dbdb771a73e90179fcb"},
{file = "pydantic-1.10.16-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4fa86469fd46e732242c7acb83282d33f83591a7e06f840481327d5bf6d96112"},
{file = "pydantic-1.10.16-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:89c2783dc261726fe7a5ce1121bce29a2f7eb9b1e704c68df2b117604e3b346f"},
{file = "pydantic-1.10.16-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78e59fa919fa7a192f423d190d8660c35dd444efa9216662273f36826765424b"},
{file = "pydantic-1.10.16-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7e82a80068c77f4b074032e031e642530b6d45cb8121fc7c99faa31fb6c6b72"},
{file = "pydantic-1.10.16-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d82d5956cee27a30e26a5b88d00a6a2a15a4855e13c9baf50175976de0dc282c"},
{file = "pydantic-1.10.16-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b7b99424cc0970ff08deccb549b5a6ec1040c0b449eab91723e64df2bd8fdca"},
{file = "pydantic-1.10.16-cp38-cp38-win_amd64.whl", hash = "sha256:d97a35e1ba59442775201657171f601a2879e63517a55862a51f8d67cdfc0017"},
{file = "pydantic-1.10.16-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9d91f6866fd3e303c632207813ef6bc4d86055e21c5e5a0a311983a9ac5f0192"},
{file = "pydantic-1.10.16-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d8d3c71d14c8bd26d2350c081908dbf59d5a6a8f9596d9ef2b09cc1e61c8662b"},
{file = "pydantic-1.10.16-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b73e6386b439b4881d79244e9fc1e32d1e31e8d784673f5d58a000550c94a6c0"},
{file = "pydantic-1.10.16-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f039881fb2ef86f6de6eacce6e71701b47500355738367413ccc1550b2a69cf"},
{file = "pydantic-1.10.16-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3895ddb26f22bdddee7e49741486aa7b389258c6f6771943e87fc00eabd79134"},
{file = "pydantic-1.10.16-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:55b945da2756b5cef93d792521ad0d457fdf2f69fd5a2d10a27513f5281717dd"},
{file = "pydantic-1.10.16-cp39-cp39-win_amd64.whl", hash = "sha256:22dd265c77c3976a34be78409b128cb84629284dfd1b69d2fa1507a36f84dc8b"},
{file = "pydantic-1.10.16-py3-none-any.whl", hash = "sha256:aa2774ba5412fd1c5cb890d08e8b0a3bb5765898913ba1f61a65a4810f03cf29"},
{file = "pydantic-1.10.16.tar.gz", hash = "sha256:8bb388f6244809af69ee384900b10b677a69f1980fdc655ea419710cffcb5610"},
]
[package.dependencies]
@@ -1066,13 +1066,13 @@ files = [
[[package]]
name = "requests"
version = "2.32.2"
version = "2.32.3"
description = "Python HTTP for Humans."
optional = false
python-versions = ">=3.8"
files = [
{file = "requests-2.32.2-py3-none-any.whl", hash = "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"},
{file = "requests-2.32.2.tar.gz", hash = "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289"},
{file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"},
{file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"},
]
[package.dependencies]
@@ -1087,13 +1087,13 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "requests-cache"
version = "1.2.0"
version = "1.2.1"
description = "A persistent cache for python requests"
optional = false
python-versions = ">=3.8"
files = [
{file = "requests_cache-1.2.0-py3-none-any.whl", hash = "sha256:490324301bf0cb924ff4e6324bd2613453e7e1f847353928b08adb0fdfb7f722"},
{file = "requests_cache-1.2.0.tar.gz", hash = "sha256:db1c709ca343cc1cd5b6c8b1a5387298eceed02306a6040760db538c885e3838"},
{file = "requests_cache-1.2.1-py3-none-any.whl", hash = "sha256:1285151cddf5331067baa82598afe2d47c7495a1334bfe7a7d329b43e9fd3603"},
{file = "requests_cache-1.2.1.tar.gz", hash = "sha256:68abc986fdc5b8d0911318fbb5f7c80eebcd4d01bfacc6685ecf8876052511d1"},
]
[package.dependencies]
@@ -1134,18 +1134,18 @@ fixture = ["fixtures"]
[[package]]
name = "setuptools"
version = "70.0.0"
version = "70.1.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
python-versions = ">=3.8"
files = [
{file = "setuptools-70.0.0-py3-none-any.whl", hash = "sha256:54faa7f2e8d2d11bcd2c07bed282eef1046b5c080d1c32add737d7b5817b1ad4"},
{file = "setuptools-70.0.0.tar.gz", hash = "sha256:f211a66637b8fa059bb28183da127d4e86396c991a942b028c6650d4319c3fd0"},
{file = "setuptools-70.1.0-py3-none-any.whl", hash = "sha256:d9b8b771455a97c8a9f3ab3448ebe0b29b5e105f1228bba41028be116985a267"},
{file = "setuptools-70.1.0.tar.gz", hash = "sha256:01a1e793faa5bd89abc851fa15d0a0db26f160890c7102cd8dce643e886b47f5"},
]
[package.extras]
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
testing = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
testing = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
[[package]]
name = "six"
@@ -1160,13 +1160,13 @@ files = [
[[package]]
name = "tenacity"
version = "8.3.0"
version = "8.4.1"
description = "Retry code until it succeeds"
optional = false
python-versions = ">=3.8"
files = [
{file = "tenacity-8.3.0-py3-none-any.whl", hash = "sha256:3649f6443dbc0d9b01b9d8020a9c4ec7a1ff5f6f3c6c8a036ef371f573fe9185"},
{file = "tenacity-8.3.0.tar.gz", hash = "sha256:953d4e6ad24357bceffbc9707bc74349aca9d245f68eb65419cf0c249a1949a2"},
{file = "tenacity-8.4.1-py3-none-any.whl", hash = "sha256:28522e692eda3e1b8f5e99c51464efcc0b9fc86933da92415168bc1c4e2308fa"},
{file = "tenacity-8.4.1.tar.gz", hash = "sha256:54b1412b878ddf7e1f1577cd49527bad8cdef32421bd599beac0c6c3f10582fd"},
]
[package.extras]
@@ -1186,13 +1186,13 @@ files = [
[[package]]
name = "typing-extensions"
version = "4.11.0"
version = "4.12.2"
description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
python-versions = ">=3.8"
files = [
{file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"},
{file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"},
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
]
[[package]]
@@ -1211,13 +1211,13 @@ six = "*"
[[package]]
name = "urllib3"
version = "2.2.1"
version = "2.2.2"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
python-versions = ">=3.8"
files = [
{file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
{file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
{file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
{file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
]
[package.extras]
@@ -1322,4 +1322,4 @@ files = [
[metadata]
lock-version = "2.0"
python-versions = "^3.9,<3.12"
content-hash = "64a5d2e5e85ad74cbb53a4395ac422f44e923cbd418171327c4dc49f47167f74"
content-hash = "912963301c039ac2f732e49803dddb895253a3f531d279fb210b45c6ea2e435a"

View File

@@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
version = "0.6.2"
version = "1.0.0"
name = "source-snapchat-marketing"
description = "Source implementation for Snapchat Marketing."
authors = [ "Airbyte <contact@airbyte.io>",]
@@ -17,7 +17,7 @@ include = "source_snapchat_marketing"
[tool.poetry.dependencies]
python = "^3.9,<3.12"
airbyte-cdk = "0.90.0"
airbyte-cdk = "^1"
[tool.poetry.scripts]
source-snapchat-marketing = "source_snapchat_marketing.run:run"

View File

@@ -1,79 +0,0 @@
{
"type": ["null", "object"],
"properties": {
"id": {
"description": "The unique identifier for the ad account.",
"type": ["null", "string"]
},
"updated_at": {
"description": "The timestamp when the ad account details were last updated.",
"type": ["null", "string"]
},
"created_at": {
"description": "The timestamp when the ad account was created.",
"type": ["null", "string"]
},
"name": {
"description": "The name or title of the ad account.",
"type": ["null", "string"]
},
"type": {
"description": "The type or category of the ad account.",
"type": ["null", "string"]
},
"status": {
"description": "The current status or state of the ad account.",
"type": ["null", "string"]
},
"organization_id": {
"description": "The ID of the organization that owns the ad account.",
"type": ["null", "string"]
},
"funding_source_ids": {
"description": "IDs of the funding sources linked to the ad account.",
"type": ["null", "array"],
"items": {
"description": "Individual funding source ID.",
"type": ["null", "string"]
}
},
"currency": {
"description": "The currency used for financial transactions within the ad account.",
"type": ["null", "string"]
},
"timezone": {
"description": "The timezone setting for the ad account operations.",
"type": ["null", "string"]
},
"advertiser_organization_id": {
"description": "The ID of the organization that is advertising on the platform.",
"type": ["null", "string"]
},
"billing_center_id": {
"description": "The ID of the billing center associated with the ad account.",
"type": ["null", "string"]
},
"billing_type": {
"description": "The type of billing arrangement for the ad account.",
"type": ["null", "string"]
},
"agency_representing_client": {
"description": "The agency representing the client for ad account management.",
"type": ["null", "boolean"]
},
"client_paying_invoices": {
"description": "Indicates if the client is responsible for paying the invoices.",
"type": ["null", "boolean"]
},
"regulations": {
"description": "Regulatory information associated with the ad account.",
"type": ["null", "object"],
"properties": {
"restricted_delivery_signals": {
"description": "Signals or content types subject to delivery restrictions.",
"type": ["null", "boolean"]
}
}
}
}
}

View File

@@ -1,59 +0,0 @@
{
"type": ["null", "object"],
"properties": {
"id": {
"description": "The unique identifier of the ad.",
"type": ["null", "string"]
},
"updated_at": {
"description": "The date and time when the ad was last updated.",
"type": ["null", "string"]
},
"created_at": {
"description": "The date and time when the ad was created.",
"type": ["null", "string"]
},
"name": {
"description": "The name or title of the ad.",
"type": ["null", "string"]
},
"ad_squad_id": {
"description": "The unique identifier of the ad squad this ad belongs to.",
"type": ["null", "string"]
},
"creative_id": {
"description": "The unique identifier of the creative content used in the ad.",
"type": ["null", "string"]
},
"status": {
"description": "The current status of the ad.",
"type": ["null", "string"]
},
"type": {
"description": "The type or category of the ad.",
"type": ["null", "string"]
},
"render_type": {
"description": "The type of rendering used for the ad.",
"type": ["null", "string"]
},
"review_status": {
"description": "The review status of the ad.",
"type": ["null", "string"]
},
"review_status_reasons": {
"description": "Reasons for the review status of the ad.",
"type": ["null", "array"],
"items": {
"type": ["null", "string"]
}
},
"delivery_status": {
"description": "The delivery status of the ad.",
"type": ["null", "array"],
"items": {
"type": ["null", "string"]
}
}
}
}

View File

@@ -1,263 +0,0 @@
{
"type": ["null", "object"],
"properties": {
"id": {
"description": "Unique identifier for the ad squad.",
"type": ["null", "string"]
},
"updated_at": {
"description": "Timestamp indicating when the ad squad was last updated.",
"type": ["null", "string"]
},
"created_at": {
"description": "Timestamp indicating when the ad squad was created.",
"type": ["null", "string"]
},
"name": {
"description": "Name of the ad squad.",
"type": ["null", "string"]
},
"status": {
"description": "Current status of the ad squad.",
"type": ["null", "string"]
},
"campaign_id": {
"description": "ID of the campaign associated with the ad squad.",
"type": ["null", "string"]
},
"type": {
"description": "Type of the ad squad.",
"type": ["null", "string"]
},
"targeting": {
"description": "Targeting settings for the ad squad.",
"type": ["null", "object"],
"properties": {
"regulated_content": {
"description": "Indicates whether regulated content targeting is enabled.",
"type": ["null", "boolean"]
},
"geos": {
"description": "Geographic targeting criteria.",
"type": ["null", "array"],
"items": {
"description": "Individual geographic item.",
"type": ["null", "object"],
"properties": {
"country_code": {
"description": "Country code for geographic targeting.",
"type": ["null", "string"]
},
"operation": {
"description": "Operation applied for geographic targeting.",
"type": ["null", "string"]
}
}
}
},
"locations": {
"description": "Location targeting criteria.",
"type": ["null", "array"],
"items": {
"description": "Individual location item.",
"type": ["null", "object"],
"properties": {
"circles": {
"description": "Circular location details.",
"type": ["null", "array"],
"items": {
"description": "Individual circle item.",
"type": ["null", "object"],
"properties": {
"latitude": {
"description": "Latitude coordinate of the circle center.",
"type": ["null", "number"]
},
"longitude": {
"description": "Longitude coordinate of the circle center.",
"type": ["null", "number"]
},
"name": {
"description": "Name of the circle location.",
"type": ["null", "string"]
},
"radius": {
"description": "Radius of the circle in specified unit.",
"type": ["null", "number"]
},
"unit": {
"description": "Unit used to measure the radius of the circle.",
"type": ["null", "string"]
}
}
}
},
"operation": {
"description": "Operation applied for location targeting.",
"type": ["null", "string"]
}
}
}
},
"auto_expansion_options": {
"description": "Options for automatic expansion in targeting.",
"type": ["null", "object"],
"properties": {
"interest_expansion_option": {
"description": "Settings for interest expansion option.",
"type": ["null", "object"],
"properties": {
"enabled": {
"description": "Indicates whether interest expansion is enabled.",
"type": ["null", "boolean"]
}
}
}
}
},
"enable_targeting_expansion": {
"description": "Option to enable targeting expansion.",
"type": ["null", "boolean"]
},
"interests": {
"description": "Interest targeting criteria.",
"type": ["null", "array"],
"items": {
"description": "Individual interest item.",
"type": ["null", "object"],
"properties": {
"category_id": {
"description": "Category ID for interest targeting.",
"type": ["null", "array"],
"items": {
"description": "Individual category ID item.",
"type": ["null", "string"]
}
},
"operation": {
"description": "Operation applied for interest targeting.",
"type": ["null", "string"]
}
}
}
},
"demographics": {
"description": "Demographic targeting criteria.",
"type": ["null", "array"],
"items": {
"description": "Individual demographic item.",
"type": ["null", "object"]
}
}
}
},
"targeting_reach_status": {
"description": "Status of targeting reach for the ad squad.",
"type": ["null", "string"]
},
"placement": {
"description": "Ad placement settings for the ad squad.",
"type": ["null", "string"]
},
"billing_event": {
"description": "Defines the billing event for the ad squad.",
"type": ["null", "string"]
},
"auto_bid": {
"description": "Indicates whether the ad squad is using auto-bidding for its bids.",
"type": ["null", "boolean"]
},
"target_bid": {
"description": "Target bid value for the ad squad.",
"type": ["null", "boolean"]
},
"bid_strategy": {
"description": "Specifies the bidding strategy used by the ad squad.",
"type": ["null", "string"]
},
"daily_budget_micro": {
"description": "Daily budget in micro currency units for the ad squad.",
"type": ["null", "integer"]
},
"start_time": {
"description": "Start time for the ad squad's run.",
"type": ["null", "string"]
},
"optimization_goal": {
"description": "Goal used for optimizing ad delivery.",
"type": ["null", "string"]
},
"delivery_constraint": {
"description": "Constraints applied to the delivery of the ad squad.",
"type": ["null", "string"]
},
"delivery_properties_version": {
"description": "Version of delivery properties for the ad squad.",
"type": ["null", "integer"]
},
"pacing_type": {
"description": "Type of pacing applied to the ad squad's delivery.",
"type": ["null", "string"]
},
"child_ad_type": {
"description": "Type of child ads under the ad squad.",
"type": ["null", "string"]
},
"forced_view_setting": {
"description": "Setting to force views for the ad squad.",
"type": ["null", "string"]
},
"creation_state": {
"description": "Current state of the ad squad creation process.",
"type": ["null", "string"]
},
"delivery_status": {
"description": "Status of ad delivery for the ad squad.",
"type": ["null", "array"],
"items": {
"description": "Individual delivery status item.",
"type": ["null", "string"]
}
},
"event_sources": {
"description": "Sources of events associated with the ad squad.",
"type": ["null", "object"],
"properties": {
"PLACE": {
"description": "Event source related to a specific place.",
"type": ["null", "array"],
"items": {
"description": "Individual event source item.",
"type": ["null", "string"]
}
}
}
},
"skadnetwork_properties": {
"description": "Properties related to SKAdNetwork integration for the ad squad.",
"type": ["null", "object"],
"properties": {
"ecid_enrollment_status": {
"description": "Status of ECID enrollment.",
"type": ["null", "string"]
},
"enable_skoverlay": {
"description": "Option to enable SKOverlay.",
"type": ["null", "boolean"]
},
"status": {
"description": "Current status of SKAdNetwork.",
"type": ["null", "string"]
}
}
},
"lifetime_budget_micro": {
"description": "Total budget in micro currency units for the lifetime of the ad squad.",
"type": ["null", "integer"]
},
"end_time": {
"description": "End time for the ad squad's run.",
"type": ["null", "string"]
}
}
}

View File

@@ -1,307 +0,0 @@
{
"type": ["null", "object"],
"properties": {
"id": {
"description": "Identifier for the data entry.",
"type": ["string"]
},
"type": {
"description": "Type of data entry.",
"type": ["string"]
},
"granularity": {
"description": "Granularity of the data.",
"type": ["string"]
},
"start_time": {
"description": "Start time of the data snapshot.",
"type": ["null", "string"],
"format": "date-time"
},
"end_time": {
"description": "End time of the data snapshot.",
"type": ["null", "string"],
"format": "date-time"
},
"android_installs": {
"description": "Total number of installs on Android devices.",
"type": ["null", "number"]
},
"attachment_avg_view_time_millis": {
"description": "Average time in milliseconds a viewer spends viewing an attachment.",
"type": ["null", "number"]
},
"attachment_impressions": {
"description": "Total number of times an attachment is displayed to users.",
"type": ["null", "number"]
},
"attachment_quartile_1": {
"description": "First quartile of attachment viewing time.",
"type": ["null", "number"]
},
"attachment_quartile_2": {
"description": "Second quartile of attachment viewing time.",
"type": ["null", "number"]
},
"attachment_quartile_3": {
"description": "Third quartile of attachment viewing time.",
"type": ["null", "number"]
},
"attachment_total_view_time_millis": {
"description": "Total time in milliseconds viewers spend on attachment views.",
"type": ["null", "number"]
},
"attachment_view_completion": {
"description": "Percentage of attachment views that are completed.",
"type": ["null", "number"]
},
"avg_screen_time_millis": {
"description": "Average time in milliseconds users spent on the screen.",
"type": ["null", "number"]
},
"avg_view_time_millis": {
"description": "Average time in milliseconds viewers spend on viewing content.",
"type": ["null", "number"]
},
"impressions": {
"description": "Total number of impressions recorded.",
"type": ["null", "number"]
},
"ios_installs": {
"description": "Total number of installs on iOS devices.",
"type": ["null", "number"]
},
"quartile_1": {
"description": "First quartile of viewing time.",
"type": ["null", "number"]
},
"quartile_2": {
"description": "Second quartile of viewing time.",
"type": ["null", "number"]
},
"quartile_3": {
"description": "Third quartile of viewing time.",
"type": ["null", "number"]
},
"screen_time_millis": {
"description": "Total time in milliseconds users spend on the screen.",
"type": ["null", "number"]
},
"spend": {
"description": "Total spend for marketing activities.",
"type": ["null", "number"]
},
"swipe_up_percent": {
"description": "Percentage of users who swiped up.",
"type": ["null", "number"]
},
"swipes": {
"description": "Total number of swipe gestures.",
"type": ["null", "number"]
},
"total_installs": {
"description": "Total number of installations.",
"type": ["null", "number"]
},
"video_views": {
"description": "Total number of video views.",
"type": ["null", "number"]
},
"video_views_time_based": {
"description": "Video views based on time duration.",
"type": ["null", "number"]
},
"video_views_15s": {
"description": "Total number of video views that last at least 15 seconds.",
"type": ["null", "number"]
},
"view_completion": {
"description": "Percentage of views that are completed.",
"type": ["null", "number"]
},
"view_time_millis": {
"description": "Total time viewers spend on viewing content in milliseconds.",
"type": ["null", "number"]
},
"paid_impressions": {
"description": "Total number of impressions from paid sources.",
"type": ["null", "number"]
},
"earned_impressions": {
"description": "Imprressions earned through engagements.",
"type": ["null", "number"]
},
"total_impressions": {
"description": "Total number of impressions including earned and paid.",
"type": ["null", "number"]
},
"play_time_millis": {
"description": "Total time in milliseconds users spend playing content.",
"type": ["null", "number"]
},
"shares": {
"description": "Total number of content shares.",
"type": ["null", "number"]
},
"saves": {
"description": "Number of saves performed.",
"type": ["null", "number"]
},
"native_leads": {
"description": "Number of leads generated natively.",
"type": ["null", "number"]
},
"conversion_purchases": {
"description": "Number of total purchases made.",
"type": ["null", "number"]
},
"conversion_purchases_value": {
"description": "Total value of purchases made.",
"type": ["null", "number"]
},
"conversion_save": {
"description": "Number of saves performed.",
"type": ["null", "number"]
},
"conversion_start_checkout": {
"description": "Number of times checkout process is initiated.",
"type": ["null", "number"]
},
"conversion_add_cart": {
"description": "Conversion events where items are added to cart.",
"type": ["null", "number"]
},
"conversion_view_content": {
"description": "Number of content views.",
"type": ["null", "number"]
},
"conversion_add_billing": {
"description": "Conversion events where billing information is added.",
"type": ["null", "number"]
},
"conversion_searches": {
"description": "Number of search queries made.",
"type": ["null", "number"]
},
"conversion_level_completes": {
"description": "Number of game levels completed.",
"type": ["null", "number"]
},
"conversion_app_opens": {
"description": "Number of times the app is opened.",
"type": ["null", "number"]
},
"conversion_page_views": {
"description": "Total number of page views.",
"type": ["null", "number"]
},
"conversion_subscribe": {
"description": "Number of subscriptions made.",
"type": ["null", "number"]
},
"conversion_ad_click": {
"description": "Number of ad clicks recorded.",
"type": ["null", "number"]
},
"conversion_ad_view": {
"description": "Number of ad views.",
"type": ["null", "number"]
},
"conversion_complete_tutorial": {
"description": "Number of completed tutorials.",
"type": ["null", "number"]
},
"conversion_invite": {
"description": "Number of invitations sent by users.",
"type": ["null", "number"]
},
"conversion_login": {
"description": "Number of logins recorded.",
"type": ["null", "number"]
},
"conversion_share": {
"description": "Number of shares made.",
"type": ["null", "number"]
},
"conversion_reserve": {
"description": "Reserve conversion events.",
"type": ["null", "number"]
},
"conversion_achievement_unlocked": {
"description": "Number of times achievements are unlocked.",
"type": ["null", "number"]
},
"conversion_add_to_wishlist": {
"description": "Conversion events where items are added to the wishlist.",
"type": ["null", "number"]
},
"conversion_spend_credits": {
"description": "Total credits spent during conversion events.",
"type": ["null", "number"]
},
"conversion_rate": {
"description": "Rate of conversion events.",
"type": ["null", "number"]
},
"conversion_start_trial": {
"description": "Number of trials started.",
"type": ["null", "number"]
},
"conversion_list_view": {
"description": "Number of views on the list content.",
"type": ["null", "number"]
},
"custom_event_1": {
"description": "Custom event tracking 1.",
"type": ["null", "number"]
},
"custom_event_2": {
"description": "Custom event tracking 2.",
"type": ["null", "number"]
},
"custom_event_3": {
"description": "Custom event tracking 3.",
"type": ["null", "number"]
},
"custom_event_4": {
"description": "Custom event tracking 4.",
"type": ["null", "number"]
},
"custom_event_5": {
"description": "Custom event tracking 5.",
"type": ["null", "number"]
},
"attachment_frequency": {
"description": "Frequency of attachment views.",
"type": ["null", "number"]
},
"attachment_uniques": {
"description": "Unique viewers of attachments.",
"type": ["null", "number"]
},
"frequency": {
"description": "Frequency of events tracked.",
"type": ["null", "number"]
},
"uniques": {
"description": "Total unique events or users.",
"type": ["null", "number"]
},
"total_reach": {
"description": "Total reach including earned and paid.",
"type": ["null", "number"]
},
"earned_reach": {
"description": "Total reach earned through engagements.",
"type": ["null", "number"]
},
"story_opens": {
"description": "Total number of story opens.",
"type": ["null", "number"]
},
"story_completes": {
"description": "Total number of completed stories.",
"type": ["null", "number"]
}
}
}

View File

@@ -1,52 +0,0 @@
{
"type": ["null", "object"],
"properties": {
"id": {
"description": "The unique identifier of the campaign.",
"type": ["null", "string"]
},
"updated_at": {
"description": "The timestamp indicating when the campaign was last updated.",
"type": ["null", "string"]
},
"created_at": {
"description": "The timestamp indicating when the campaign was created.",
"type": ["null", "string"]
},
"name": {
"description": "The name assigned to the campaign for easy identification.",
"type": ["null", "string"]
},
"ad_account_id": {
"description": "The unique identifier of the advertising account associated with the campaign.",
"type": ["null", "string"]
},
"status": {
"description": "The current status of the campaign (e.g., paused, active).",
"type": ["null", "string"]
},
"objective": {
"description": "The primary goal or objective of the campaign.",
"type": ["null", "string"]
},
"start_time": {
"description": "The starting date and time for the campaign to begin running.",
"type": ["null", "string"]
},
"buy_model": {
"description": "The purchasing model used for the campaign (e.g., auction, reach and frequency).",
"type": ["null", "string"]
},
"delivery_status": {
"description": "The status of campaign delivery.",
"type": ["null", "array"],
"items": {
"type": ["null", "string"]
}
},
"creation_state": {
"description": "The current state of the campaign creation process.",
"type": ["null", "string"]
}
}
}

View File

@@ -1,113 +0,0 @@
{
"type": ["null", "object"],
"properties": {
"id": {
"description": "The unique identifier of the creative",
"type": ["null", "string"]
},
"updated_at": {
"description": "The timestamp indicating when the creative was last updated",
"type": ["null", "string"]
},
"created_at": {
"description": "The timestamp indicating when the creative was created",
"type": ["null", "string"]
},
"name": {
"description": "The name or title given to the creative",
"type": ["null", "string"]
},
"ad_account_id": {
"description": "The ID of the advertising account linked to the creative",
"type": ["null", "string"]
},
"type": {
"description": "The type or category of the creative",
"type": ["null", "string"]
},
"packaging_status": {
"description": "The status of the packaging for the creative",
"type": ["null", "string"]
},
"review_status": {
"description": "The overall review status of the creative",
"type": ["null", "string"]
},
"review_status_details": {
"description": "Additional details related to the review status",
"type": ["null", "string"]
},
"shareable": {
"description": "Indicates if the creative is shareable",
"type": ["null", "boolean"]
},
"forced_view_eligibility": {
"description": "Whether the creative is eligible for forced views",
"type": ["null", "string"]
},
"headline": {
"description": "The headline or title of the creative",
"type": ["null", "string"]
},
"brand_name": {
"description": "The name of the brand associated with the creative",
"type": ["null", "string"]
},
"call_to_action": {
"description": "The call to action prompt for the creative",
"type": ["null", "string"]
},
"render_type": {
"description": "The type of rendering used for the creative",
"type": ["null", "string"]
},
"top_snap_media_id": {
"description": "The ID of the media file for the top snap",
"type": ["null", "string"]
},
"top_snap_crop_position": {
"description": "The crop position for the top snap of the creative",
"type": ["null", "string"]
},
"web_view_properties": {
"description": "Properties related to the web view functionality when a user interacts with the ad.",
"type": ["null", "object"],
"properties": {
"url": {
"description": "The URL to be loaded in the web view",
"type": ["null", "string"]
},
"allow_snap_javascript_sdk": {
"description": "Whether to allow the use of Snap JavaScript SDK in the web view",
"type": ["null", "boolean"]
},
"use_immersive_mode": {
"description": "Whether to use immersive mode in the web view",
"type": ["null", "boolean"]
},
"deep_link_urls": {
"description": "List of deep link URLs associated with the web view",
"type": ["null", "array"]
},
"block_preload": {
"description": "Indicates if preloading is blocked for the web view",
"type": ["null", "boolean"]
}
}
},
"ad_product": {
"description": "The type of Snapchat advertising product used for the creative",
"type": ["null", "string"]
},
"ad_to_place_properties": {
"description": "Properties related to the ad to be displayed within the Snapchat interface.",
"type": ["null", "object"],
"properties": {
"place_id": {
"description": "The ID of the place where the ad is to be displayed",
"type": ["null", "string"]
}
}
}
}
}

View File

@@ -1,78 +0,0 @@
{
"type": ["null", "object"],
"properties": {
"id": {
"description": "The unique identifier of the media.",
"type": ["null", "string"]
},
"updated_at": {
"description": "The timestamp when the media was last updated.",
"type": ["null", "string"]
},
"created_at": {
"description": "The timestamp when the media was created.",
"type": ["null", "string"]
},
"ad_account_id": {
"description": "The unique identifier of the ad account associated with the media.",
"type": ["null", "string"]
},
"type": {
"description": "The type of media (e.g., image, video).",
"type": ["null", "string"]
},
"media_status": {
"description": "The status of the media (e.g., active, inactive).",
"type": ["null", "string"]
},
"media_usages": {
"description": "Items associated with the media usage.",
"type": ["null", "array"],
"items": {
"description": "Details of the media usage.",
"type": ["null", "string"]
}
},
"file_name": {
"description": "The name of the media file.",
"type": ["null", "string"]
},
"download_link": {
"description": "The link to download the media file.",
"type": ["null", "string"]
},
"duration_in_seconds": {
"description": "The duration of the media in seconds.",
"type": ["null", "number"],
"multipleOf": 1e-10
},
"image_metadata": {
"description": "Additional metadata related to the image media.",
"type": ["null", "object"]
},
"video_metadata": {
"description": "Additional metadata related to the video media.",
"type": ["null", "object"]
},
"file_size_in_bytes": {
"description": "The file size of the media in bytes.",
"type": ["null", "integer"]
},
"is_demo_media": {
"description": "Indicates if the media is a demo or not.",
"type": ["null", "boolean"]
},
"hash": {
"description": "The hash value of the media file for identification purposes.",
"type": ["null", "string"]
},
"visibility": {
"description": "The visibility settings of the media (e.g., public, private).",
"type": ["null", "string"]
},
"name": {
"description": "The name or title of the media.",
"type": ["null", "string"]
}
}
}

View File

@@ -1,103 +0,0 @@
{
"type": ["null", "object"],
"properties": {
"id": {
"description": "Unique identifier for the organization record.",
"type": ["null", "string"]
},
"updated_at": {
"description": "Timestamp indicating the last update date of the organization record.",
"type": ["null", "string"]
},
"created_at": {
"description": "Timestamp indicating the creation date of the organization record.",
"type": ["null", "string"]
},
"name": {
"description": "The name of the organization.",
"type": ["null", "string"]
},
"country": {
"description": "The country where the organization is located.",
"type": ["null", "string"]
},
"postal_code": {
"description": "The postal code of the organization's location.",
"type": ["null", "string"]
},
"locality": {
"description": "The locality or city where the organization is situated.",
"type": ["null", "string"]
},
"contact_name": {
"description": "The name of the contact person within the organization.",
"type": ["null", "string"]
},
"contact_email": {
"description": "The email address used for contact purposes.",
"type": ["null", "string"]
},
"contact_phone": {
"description": "The phone number of the contact person within the organization.",
"type": ["null", "string"]
},
"address_line_1": {
"description": "The first line of the organization's address.",
"type": ["null", "string"]
},
"administrative_district_level_1": {
"description": "The first-level administrative district of the organization's location.",
"type": ["null", "string"]
},
"accepted_term_version": {
"description": "The version of the terms and conditions accepted by the organization.",
"type": ["null", "string"]
},
"contact_phone_optin": {
"description": "Flag indicating if contact person has opted in for phone contact.",
"type": ["null", "boolean"]
},
"configuration_settings": {
"description": "Settings related to organization configurations",
"type": ["null", "object"],
"properties": {
"notifications_enabled": {
"description": "Flag indicating if notifications are enabled for the organization.",
"type": ["null", "boolean"]
}
}
},
"type": {
"description": "The type or category of the organization.",
"type": ["null", "string"]
},
"state": {
"description": "The state or region where the organization is located.",
"type": ["null", "string"]
},
"roles": {
"description": "List of roles assigned to the organization.",
"type": ["null", "array"],
"items": {
"description": "A specific role assigned to the organization.",
"type": ["null", "string"]
}
},
"my_display_name": {
"description": "The public display name of the organization.",
"type": ["null", "string"]
},
"my_invited_email": {
"description": "Email address of the member invited to the organization.",
"type": ["null", "string"]
},
"my_member_id": {
"description": "Unique identifier of the member within the organization.",
"type": ["null", "string"]
},
"createdByCaller": {
"description": "Record of the creator of the organization within the system.",
"type": ["null", "boolean"]
}
}
}

View File

@@ -1,64 +0,0 @@
{
"type": ["null", "object"],
"properties": {
"id": {
"description": "Unique identifier for the segment",
"type": ["null", "string"]
},
"updated_at": {
"description": "The date and time when the segment was last updated",
"type": ["null", "string"]
},
"created_at": {
"description": "The date and time when the segment was created",
"type": ["null", "string"]
},
"name": {
"description": "Name or title of the segment",
"type": ["null", "string"]
},
"ad_account_id": {
"description": "The unique identifier for the ad account associated with the segment",
"type": ["null", "string"]
},
"organization_id": {
"description": "Unique identifier for the organization to which the segment belongs",
"type": ["null", "string"]
},
"description": {
"description": "Brief description of the segment",
"type": ["null", "string"]
},
"status": {
"description": "Current status of the segment (e.g., active, inactive)",
"type": ["null", "string"]
},
"targetable_status": {
"description": "Status indicating whether the segment can be targeted in marketing campaigns",
"type": ["null", "string"]
},
"upload_status": {
"description": "Status of the segment upload process (e.g., pending, completed)",
"type": ["null", "string"]
},
"source_type": {
"description": "Type of the source data used to create the segment",
"type": ["null", "string"]
},
"retention_in_days": {
"description": "Number of days for which the segment data is retained",
"type": ["null", "integer"]
},
"approximate_number_users": {
"description": "Approximate number of users within the segment",
"type": ["null", "integer"]
},
"visible_to": {
"description": "Visibility setting for the segment, determining who can access it",
"type": ["null", "array"],
"items": {
"type": ["null", "string"]
}
}
}
}

View File

@@ -2,826 +2,17 @@
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
#
import logging
from abc import ABC, abstractmethod
from enum import Enum
from typing import Any, Iterable, List, Mapping, MutableMapping, Optional, Tuple
from urllib.parse import parse_qsl, urlparse
from airbyte_cdk.sources.declarative.yaml_declarative_source import YamlDeclarativeSource
import backoff
import pendulum
import requests
from airbyte_cdk.models import SyncMode
from airbyte_cdk.sources import AbstractSource
from airbyte_cdk.sources.streams import Stream
from airbyte_cdk.sources.streams.core import IncrementalMixin, package_name_from_class
from airbyte_cdk.sources.streams.http import HttpStream
from airbyte_cdk.sources.streams.http.requests_native_auth import Oauth2Authenticator
from airbyte_cdk.sources.utils.schema_helpers import ResourceSchemaLoader
"""
This file provides the necessary constructs to interpret a provided declarative YAML configuration file into
source connector.
# https://marketingapi.snapchat.com/docs/#core-metrics
# https://marketingapi.snapchat.com/docs/#metrics-and-supported-granularities
METRICS = [
"android_installs",
"attachment_avg_view_time_millis",
"attachment_impressions",
"attachment_quartile_1",
"attachment_quartile_2",
"attachment_quartile_3",
"attachment_total_view_time_millis",
"attachment_view_completion",
"avg_screen_time_millis",
"avg_view_time_millis",
"impressions",
"ios_installs",
"quartile_1",
"quartile_2",
"quartile_3",
"screen_time_millis",
"spend",
"swipe_up_percent",
"swipes",
"total_installs",
"video_views",
"video_views_time_based",
"video_views_15s",
"view_completion",
"view_time_millis",
"paid_impressions",
"earned_impressions",
"total_impressions",
"play_time_millis",
"shares",
"saves",
"native_leads",
"conversion_purchases",
"conversion_purchases_value",
"conversion_save",
"conversion_start_checkout",
"conversion_add_cart",
"conversion_view_content",
"conversion_add_billing",
# 'conversion_signups', # Invalid query parameters in request URL
"conversion_searches",
"conversion_level_completes",
"conversion_app_opens",
"conversion_page_views",
"conversion_subscribe",
"conversion_ad_click",
"conversion_ad_view",
"conversion_complete_tutorial",
"conversion_invite",
"conversion_login",
"conversion_share",
"conversion_reserve",
"conversion_achievement_unlocked",
"conversion_add_to_wishlist",
"conversion_spend_credits",
"conversion_rate",
"conversion_start_trial",
"conversion_list_view",
"custom_event_1",
"custom_event_2",
"custom_event_3",
"custom_event_4",
"custom_event_5",
"story_opens",
"story_completes",
]
WARNING: Do not modify this file.
"""
METRICS_NOT_HOURLY = [
"attachment_frequency",
"attachment_uniques",
"frequency",
"uniques",
"total_reach",
"earned_reach",
]
logger = logging.getLogger("airbyte")
class GranularityType(Enum):
HOUR = "HOUR"
DAY = "DAY"
LIFETIME = "LIFETIME"
# See the get_parent_ids function explanation
# Long story short - used as cache for ids of higher level streams, that is used
# as path variables in other streams. And to avoid requesting those ids for every stream
# we put them to a dict and check if they exist on stream calling
# The structure be like:
# {
# 'Organizations': [
# {'organization_id': '7f064d90-52a1-some-uuid'}
# ],
# 'Adaccounts': [
# {'ad_account_id': '04214c00-3aa5-some-uuid'},
# {'ad_account_id': 'e4cd371b-8de8-some-uuid'}
# ]
# }
#
auxiliary_id_map = {}
class SnapchatMarketingException(Exception):
"""Just for formatting the exception as SnapchatMarketing"""
def get_parent_ids(parent) -> List:
"""Return record ids from <parent> stream full_refresh sync, example:
[{'id': record_1['id']}, {'id': record_2['id']}, ... {'id': record_N['id']}]
Function uses global cache 'auxiliary_id_map' to save results of parent syncs.
It prevents multiple actual syncs of the same basic streams like organizations, adacounts etc
:param parent: instance of stream class from what we need to retrieve ids
:returns: empty list in case no ids of the stream was found or list with {'id': id}
"""
# return cached data if it has been already extracted
if parent.name in auxiliary_id_map:
return auxiliary_id_map[parent.name]
parent_ids = []
# Run actual sync for parent stream
parent_stream_slices = parent.stream_slices(sync_mode=SyncMode.full_refresh)
for parent_stream_slice in parent_stream_slices:
records = parent.read_records(sync_mode=SyncMode.full_refresh, stream_slice=parent_stream_slice)
for record in records:
parent_ids.append({"id": record["id"]})
# add data to cache to prevent further actual syncs of the same streams. (they always return the same data)
auxiliary_id_map[parent.name] = parent_ids
return parent_ids
class SnapchatMarketingStream(HttpStream, ABC):
url_base = "https://adsapi.snapchat.com/v1/"
primary_key = "id"
raise_on_http_errors = True
def __init__(self, start_date, end_date, action_report_time, swipe_up_attribution_window, view_attribution_window, **kwargs):
super().__init__(**kwargs)
self.start_date = start_date
self.end_date = end_date
self.action_report_time = action_report_time
self.swipe_up_attribution_window = swipe_up_attribution_window
self.view_attribution_window = view_attribution_window
def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]:
next_page_cursor = response.json().get("paging", False)
if next_page_cursor:
return {"cursor": dict(parse_qsl(urlparse(next_page_cursor["next_link"]).query))["cursor"]}
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]:
return next_page_token or {}
@property
def response_root_name(self):
"""Using the class name in lower to set the root node for response parsing"""
return self.name
@property
def response_item_name(self):
"""Remove last 's' from response_root_name, see example in parse_response function"""
return self.response_root_name[:-1]
def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]:
"""Response json came like
{
"organizations": [ <-- response_root_name
{
"organization": { <-- response_item_name
"id": "some uuid",
"updated_at": "2020-12-15T22:35:17.819Z",
"created_at": "2020-12-15T11:13:03.910Z",
... some_other_json_fields ...
}
}
]
}
So the response_root_name will be "organizations", and the response_item_name will be "organization"
Also, the client side filtering for incremental sync is used
"""
json_response = response.json().get(self.response_root_name, [])
for resp in json_response:
if self.response_item_name not in resp:
error_text = f"stream {self.name}: field named '{self.response_item_name}' is absent in the response: {resp}"
self.logger.error(error_text)
raise SnapchatMarketingException(error_text)
yield resp.get(self.response_item_name)
def should_retry(self, response: requests.Response) -> bool:
if response.status_code == 403:
setattr(self, "raise_on_http_errors", False)
self.logger.warning(f"Got permission error when accessing URL {response.request.url}. " f"Skipping {self.name} stream.")
return False
return super().should_retry(response)
class IncrementalSnapchatMarketingStream(SnapchatMarketingStream, ABC):
cursor_field = "updated_at"
last_slice = None
current_slice = None
initial_state = None
max_state = None
@property
@abstractmethod
def parent(self) -> SnapchatMarketingStream:
"""Stream Class to extract entity ids from"""
def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str:
return f"adaccounts/{stream_slice['id']}/{self.response_root_name}"
def stream_slices(self, **kwargs) -> Iterable[Optional[Mapping[str, Any]]]:
stream_state = kwargs.get("stream_state")
self.initial_state = stream_state.get(self.cursor_field) if stream_state else self.start_date
self.max_state = self.initial_state
parent_stream = self.parent(
authenticator=self._session.auth,
start_date=self.start_date,
end_date=self.end_date,
action_report_time=self.action_report_time,
swipe_up_attribution_window=self.swipe_up_attribution_window,
view_attribution_window=self.view_attribution_window,
)
stream_slices = get_parent_ids(parent_stream)
if stream_slices:
self.last_slice = stream_slices[-1]
self.logger.info(f"{self.name} stream slices: {stream_slices}")
return stream_slices
def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]:
"""
Handle state value for streams with random order of cursor_field values.
State with max value should be release only in last slice otherwise records
from intermediate slices can be filtered out in 'read_records'
"""
# store max state value across all records of all slices (parent ids) because
# cursor_field values are random (not sorted) even within one slice (parent id)
self.max_state = max(self.max_state, latest_record[self.cursor_field])
if self.current_slice == self.last_slice:
# return max found state for last slice only
return {self.cursor_field: self.max_state}
else:
# return release initial state until last slice is processed
return {self.cursor_field: self.initial_state}
def read_records(
self, stream_state: Mapping[str, Any] = None, stream_slice: Mapping[str, Any] = None, **kwargs
) -> Iterable[Mapping[str, Any]]:
"""
This structure is used to set the class variable current_slice to the current stream slice for the
purposes described above.
Then all the retrieved records if the stream_state is present are filtered by the cursor_field value compared to the stream state
This makes the incremental magic works
"""
self.current_slice = stream_slice
records = super().read_records(stream_slice=stream_slice, stream_state=stream_state, **kwargs)
if stream_state:
for record in records:
if record[self.cursor_field] > stream_state.get(self.cursor_field):
yield record
else:
yield from records
class Organizations(SnapchatMarketingStream):
"""Docs: https://marketingapi.snapchat.com/docs/#organizations"""
def path(self, **kwargs) -> str:
return "me/organizations"
class Adaccounts(IncrementalSnapchatMarketingStream):
"""Docs: https://marketingapi.snapchat.com/docs/#get-all-ad-accounts"""
parent = Organizations
def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str:
return f"organizations/{stream_slice['id']}/adaccounts"
class Creatives(IncrementalSnapchatMarketingStream):
"""Docs: https://marketingapi.snapchat.com/docs/#get-all-creatives"""
parent = Adaccounts
class Media(IncrementalSnapchatMarketingStream):
"""Docs: https://marketingapi.snapchat.com/docs/#get-all-media"""
parent = Adaccounts
@property
def response_item_name(self):
return self.response_root_name
class Campaigns(IncrementalSnapchatMarketingStream):
"""Docs: https://marketingapi.snapchat.com/docs/#get-all-campaigns"""
parent = Adaccounts
class Ads(IncrementalSnapchatMarketingStream):
"""Docs: https://marketingapi.snapchat.com/docs/#get-all-ads-under-an-ad-account"""
parent = Adaccounts
class Adsquads(IncrementalSnapchatMarketingStream):
"""Docs: https://marketingapi.snapchat.com/docs/#get-all-ad-squads-under-an-ad-account"""
parent = Adaccounts
class Segments(IncrementalSnapchatMarketingStream):
"""Docs: https://marketingapi.snapchat.com/docs/#get-all-audience-segments"""
parent = Adaccounts
class Stats(SnapchatMarketingStream, ABC):
"""Stats streams for LIFETIME granularity.
Docs: https://marketingapi.snapchat.com/docs/#measurement
"""
primary_key = ["id", "granularity"]
schema_name = "basic_stats"
parent_name: str = "" # name of parent class
response_root_name = "lifetime_stats"
granularity = GranularityType.LIFETIME
@property
@abstractmethod
def parent(self) -> SnapchatMarketingStream:
"""Stream Class to extract entity ids from"""
def stream_slices(self, **kwargs) -> Iterable[Optional[Mapping[str, Any]]]:
"""Each stream slice represents each entity id from parent stream"""
parent_stream = self.parent(
authenticator=self._session.auth,
start_date=self.start_date,
end_date=self.end_date,
action_report_time=self.action_report_time,
swipe_up_attribution_window=self.swipe_up_attribution_window,
view_attribution_window=self.view_attribution_window,
)
self.parent_name = parent_stream.name
stream_slices = get_parent_ids(parent_stream)
if not stream_slices:
self.logger.error(f"No {'id'}s found. {self.name} cannot be extracted without {'id'}.")
self.logger.info(f"Stats: stream_slices:{stream_slices}")
return stream_slices
def path(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> str:
return f"{self.parent_name}/{stream_slice['id']}/stats"
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_state, stream_slice=stream_slice, next_page_token=next_page_token)
params["granularity"] = self.granularity.value
params["action_report_time"] = self.action_report_time
params["swipe_up_attribution_window"] = self.swipe_up_attribution_window
params["view_attribution_window"] = self.view_attribution_window
if self.metrics:
params["fields"] = ",".join(self.metrics)
return params
def parse_response(
self,
response: requests.Response,
*,
stream_state: Mapping[str, Any],
stream_slice: Mapping[str, Any] = None,
next_page_token: Mapping[str, Any] = None,
) -> Iterable[Mapping]:
"""Customized by adding stream state setting"""
for record in super().parse_response(
response=response, stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token
):
# move all 'stats' metrics to root level
record.update(record.pop("stats", {}))
yield record
def get_json_schema(self) -> Mapping[str, Any]:
"""All stats streams have same schema"""
return ResourceSchemaLoader(package_name_from_class(self.__class__)).get_schema(self.schema_name)
class StatsIncremental(Stats, IncrementalMixin):
"""Incremental Stats class for Daily and Hourly streams which requires start/end date param"""
primary_key = ["id", "granularity", "start_time"]
cursor_field: str = "start_time"
slice_period: int = 7 # days https://marketingapi.snapchat.com/docs/#metrics-and-supported-granularities
number_of_parent_ids: int = 0
number_of_last_records: int = 0
response_root_name = "timeseries_stats"
response_subitem_name = "timeseries"
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._state = {}
def date_slices(self, stream_state=None) -> Iterable[Optional[Mapping[str, Any]]]:
date_slices = []
# use start_date from state or from config
start_date_str = stream_state.get(self.cursor_field) if stream_state else self.start_date
slice_start_date = pendulum.parse(start_date_str)
end_date = pendulum.parse(self.end_date)
while slice_start_date < end_date:
slice_end_date_next = slice_start_date + pendulum.duration(days=self.slice_period)
slice_end_date = min(slice_end_date_next, end_date)
date_slices.append({"start_time": slice_start_date.to_date_string(), "end_time": slice_end_date.to_date_string()})
slice_start_date = slice_end_date
self.logger.info(f"{self.name} stream date slices: {date_slices}.")
return date_slices
def stream_slices(self, stream_state: Mapping[str, Any] = None, **kwargs) -> Iterable[Optional[Mapping[str, Any]]]:
"""Incremental stream slices is a combinations of date and parent id slices"""
stream_slices = []
parent_ids = super().stream_slices()
# save a number of parent ids we need to get stats for
self.number_of_parent_ids = len(parent_ids)
# within each date period extract data for all parent_ids
# it allows incremental sync implementation with slice period granularity
for date_slice in self.date_slices(stream_state=stream_state):
for parent_id in parent_ids:
stream_slices.append({**date_slice, **parent_id})
self.logger.info(f"{self.name} stream slices: {stream_slices}")
return stream_slices
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]:
"""start/end date param should be set for Daily and Hourly streams"""
params = super().request_params(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token)
params["start_time"] = stream_slice["start_time"]
params["end_time"] = stream_slice["end_time"]
return params
def update_state_after_last_record(self, record):
"""Update state if last record has been read"""
record_end_date = record.get("end_time", "").split("T")[0] # "2022-07-06T00:00:00.000-07:00" --> "2022-07-06"
if record_end_date == self.end_date:
self.number_of_last_records += 1
# Update state if 'last' records for all dependant entities have been read
if self.number_of_parent_ids == self.number_of_last_records:
self.state = {self.cursor_field: record_end_date}
@property
def state(self):
return self._state
@state.setter
def state(self, value):
self._state = value
def parse_response(
self,
response: requests.Response,
*,
stream_state: Mapping[str, Any],
stream_slice: Mapping[str, Any] = None,
next_page_token: Mapping[str, Any] = None,
) -> Iterable[Mapping]:
"""Customized by adding stream state setting"""
# Update state for each date slice (start_date), it ensures that previous date slices have been read
# and can be skipped in next incremental sync
self.state = {self.cursor_field: stream_slice[self.cursor_field]}
for record in super().parse_response(
response=response, stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token
):
record_identifiers = {
"id": record["id"],
"type": record["type"],
"granularity": record["granularity"],
}
# Hourly/Daily stats contains nested structure (under self.response_subitem_name) with actual stats items
for stat_item in record.get(self.response_subitem_name, []):
# add common record identifiers
stat_item.update(record_identifiers)
# move all 'stats' metrics to root level
stat_item.update(stat_item.pop("stats", {}))
# Update state for last record in the stream
self.update_state_after_last_record(stat_item)
yield stat_item
class Granularity:
granularity: GranularityType
metrics = METRICS + METRICS_NOT_HOURLY
class Lifetime(Granularity):
"""Example of raw response:
{
"request_status": "SUCCESS",
"request_id": "d0cb395f-c39d-480d-b62c-24878c7d0b76",
"lifetime_stats": [{ <-- response_root_name
"sub_request_status": "SUCCESS",
"lifetime_stat": { <-- response_item_name
"id": "96e5549f-4065-490e-93dd-ffb9f7973b77",
"type": "AD",
"granularity": "LIFETIME",
"stats": {
"impressions": 0,
"swipes": 0,
"quartile_1": 0,
"quartile_2": 0,
},
"start_time": "2016-09-26T00:00:00.000-07:00",
"end_time": "2022-07-01T07:00:00.000-07:00",
"finalized_data_end_time": "2022-07-01T07:00:00.000-07:00",
"conversion_data_processed_end_time": "2022-07-01T00:00:00.000Z"
}
}
]
}
"""
granularity = GranularityType.LIFETIME
class Hourly(Granularity):
"""Example of raw response:
{
"request_status": "SUCCESS",
"request_id": "c106d757-7c07-4415-b62f-78108d9dc668",
"timeseries_stats": [{ <-- response_root_name
"sub_request_status": "SUCCESS",
"timeseries_stat": { <-- response_item_name
"id": "417d0269-80fb-496a-b5f3-ec0bac665144",
"type": "AD",
"granularity": "HOUR",
"start_time": "2022-06-24T17:00:00.000-07:00",
"end_time": "2022-06-28T17:00:00.000-07:00",
"finalized_data_end_time": "2022-06-30T11:00:00.000-07:00",
"conversion_data_processed_end_time": "2022-06-30T00:00:00.000Z",
"timeseries": [{ <-- response_subitem_name
"start_time": "2022-06-24T17:00:00.000-07:00",
"end_time": "2022-06-24T18:00:00.000-07:00",
"stats": {
"impressions": 0,
"swipes": 0,
"quartile_1": 0,
"quartile_2": 0,
"quartile_3": 0,
"view_completion": 0,
}
}, {
"start_time": "2022-06-24T18:00:00.000-07:00",
"end_time": "2022-06-24T19:00:00.000-07:00",
"stats": {
"impressions": 0,
"swipes": 0,
}
}
]
}
}
]
}
"""
granularity = GranularityType.HOUR
metrics = METRICS
slice_period = 7 # days https://marketingapi.snapchat.com/docs/#metrics-and-supported-granularities
class Daily(Granularity):
"""Example of raw response:
{
"request_status": "SUCCESS",
"request_id": "f2cba857-e246-43bf-b644-1a0a540e1f92",
"timeseries_stats": [{ <-- response_root_name
"sub_request_status": "SUCCESS",
"timeseries_stat": { <-- response_item_name
"id": "417d0269-80fb-496a-b5f3-ec0bac665144",
"type": "AD",
"granularity": "DAY",
"start_time": "2022-06-25T00:00:00.000-07:00",
"end_time": "2022-06-29T00:00:00.000-07:00",
"finalized_data_end_time": "2022-06-30T00:00:00.000-07:00",
"conversion_data_processed_end_time": "2022-06-30T00:00:00.000Z",
"timeseries": [{ <-- response_subitem_name
"start_time": "2022-06-25T00:00:00.000-07:00",
"end_time": "2022-06-26T00:00:00.000-07:00",
"stats": {
"impressions": 0,
"swipes": 0,
"quartile_1": 0,
"quartile_2": 0,
"quartile_3": 0,
}
}, {
"start_time": "2022-06-26T00:00:00.000-07:00",
"end_time": "2022-06-27T00:00:00.000-07:00",
"stats": {
"impressions": 0,
"swipes": 0,
"quartile_1": 0,
"quartile_2": 0,
"quartile_3": 0,
},
},
]
}
}
]
}
"""
granularity = GranularityType.DAY
slice_period = 31 # days https://marketingapi.snapchat.com/docs/#metrics-and-supported-granularities
class AdaccountsStatsHourly(Hourly, StatsIncremental):
"""Adaccounts stats with Hourly granularity: https://marketingapi.snapchat.com/docs/#get-ad-account-stats"""
parent = Adaccounts
metrics = ["spend"]
class AdaccountsStatsDaily(Daily, StatsIncremental):
"""Adaccounts stats with Daily granularity: https://marketingapi.snapchat.com/docs/#get-ad-account-stats"""
parent = Adaccounts
metrics = ["spend"]
class AdaccountsStatsLifetime(Lifetime, Stats):
"""Adaccounts stats with Lifetime granularity: https://marketingapi.snapchat.com/docs/#get-ad-account-stats"""
parent = Adaccounts
metrics = ["spend"]
class AdsStatsHourly(Hourly, StatsIncremental):
"""Ads stats with Hourly granularity: https://marketingapi.snapchat.com/docs/#get-ad-stats"""
parent = Ads
class AdsStatsDaily(Daily, StatsIncremental):
"""Ads stats with Daily granularity: https://marketingapi.snapchat.com/docs/#get-ad-stats"""
parent = Ads
class AdsStatsLifetime(Lifetime, Stats):
"""Ads stats with Lifetime granularity: https://marketingapi.snapchat.com/docs/#get-ad-stats"""
parent = Ads
class AdsquadsStatsHourly(Hourly, StatsIncremental):
"""Adsquads stats with Hourly granularity: https://marketingapi.snapchat.com/docs/#get-ad-squad-stats"""
parent = Adsquads
class AdsquadsStatsDaily(Daily, StatsIncremental):
"""Adsquads stats with Daily granularity: https://marketingapi.snapchat.com/docs/#get-ad-squad-stats"""
parent = Adsquads
class AdsquadsStatsLifetime(Lifetime, Stats):
"""Adsquads stats with Lifetime granularity: https://marketingapi.snapchat.com/docs/#get-ad-squad-stats"""
parent = Adsquads
class CampaignsStatsHourly(Hourly, StatsIncremental):
"""Campaigns stats with Hourly granularity: https://marketingapi.snapchat.com/docs/#get-campaign-stats"""
parent = Campaigns
class CampaignsStatsDaily(Daily, StatsIncremental):
"""Campaigns stats with Daily granularity: https://marketingapi.snapchat.com/docs/#get-campaign-stats"""
parent = Campaigns
class CampaignsStatsLifetime(Lifetime, Stats):
"""Campaigns stats with Lifetime granularity: https://marketingapi.snapchat.com/docs/#get-campaign-stats"""
parent = Campaigns
# Source
class SourceSnapchatMarketing(AbstractSource):
"""Source Snapchat Marketing helps to retrieve the different Ad data from Snapchat business account"""
def check_connection(self, logger, config) -> Tuple[bool, any]:
try:
auth = Oauth2Authenticator(
token_refresh_endpoint="https://accounts.snapchat.com/login/oauth2/access_token",
client_id=config["client_id"],
client_secret=config["client_secret"],
refresh_token=config["refresh_token"],
)
token = auth.get_access_token()
url = f"{SnapchatMarketingStream.url_base}me"
session = requests.get(url, headers={"Authorization": "Bearer {}".format(token)})
session.raise_for_status()
return True, None
except requests.exceptions.RequestException as e:
return False, e
def streams(self, config: Mapping[str, Any]) -> List[Stream]:
# https://marketingapi.snapchat.com/docs/#core-metrics
# IMPORTANT: Metrics are finalized 48 hours after the end of the day in the Ad Accounts timezone.
DELAYED_DAYS = 2
# Start/End dates should better be in YYYY-MM-DD format:
# 1. minutes are not supported
# 2. when timezone is not specified, default account's timezone will be used automatically
default_end_date = pendulum.now().subtract(days=DELAYED_DAYS).to_date_string()
kwargs = {
"authenticator": Oauth2Authenticator(
token_refresh_endpoint="https://accounts.snapchat.com/login/oauth2/access_token",
client_id=config["client_id"],
client_secret=config["client_secret"],
refresh_token=config["refresh_token"],
),
"start_date": config["start_date"],
"end_date": config.get("end_date", default_end_date),
"action_report_time": config.get("action_report_time", "conversion"),
"swipe_up_attribution_window": config.get("swipe_up_attribution_window", "28_DAY"),
"view_attribution_window": config.get("view_attribution_window", "1_DAY"),
}
return [
# Base streams:
Adaccounts(**kwargs),
Ads(**kwargs),
Adsquads(**kwargs),
Campaigns(**kwargs),
Creatives(**kwargs),
Media(**kwargs),
Organizations(**kwargs),
Segments(**kwargs),
# Stats streams:
AdaccountsStatsHourly(**kwargs),
AdaccountsStatsDaily(**kwargs),
AdaccountsStatsLifetime(**kwargs),
AdsStatsHourly(**kwargs),
AdsStatsDaily(**kwargs),
AdsStatsLifetime(**kwargs),
AdsquadsStatsHourly(**kwargs),
AdsquadsStatsDaily(**kwargs),
AdsquadsStatsLifetime(**kwargs),
CampaignsStatsHourly(**kwargs),
CampaignsStatsDaily(**kwargs),
CampaignsStatsLifetime(**kwargs),
]
# Declarative Source
class SourceSnapchatMarketing(YamlDeclarativeSource):
def __init__(self):
super().__init__(**{"path_to_yaml": "manifest.yaml"})

View File

@@ -0,0 +1,19 @@
#
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
#
from source_snapchat_marketing.source import SourceSnapchatMarketing
def find_stream(stream_name, config):
streams = SourceSnapchatMarketing().streams(config=config)
# cache should be disabled once this issue is fixed https://github.com/airbytehq/airbyte-internal-issues/issues/6513
for stream in streams:
stream.retriever.requester.use_cache = True
# find by name
for stream in streams:
if stream.name == stream_name:
return stream
raise ValueError(f"Stream {stream_name} not found")

View File

@@ -1,105 +1,63 @@
#
# Copyright (c) 2023 Airbyte, Inc., all rights reserved.
# Copyright (c) 2024 Airbyte, Inc., all rights reserved.
#
# from unittest.mock import MagicMock, PropertyMock, patch
import json
import logging
import pytest
import source_snapchat_marketing
from airbyte_cdk.models import SyncMode
from airbyte_cdk.sources.streams.http.auth import NoAuth
from source_snapchat_marketing.source import (
Adaccounts,
AdaccountsStatsDaily,
Ads,
AdsStatsDaily,
AdsStatsLifetime,
Oauth2Authenticator,
Organizations,
SourceSnapchatMarketing,
)
from airbyte_cdk.sources.declarative.types import StreamSlice
from airbyte_cdk.sources.streams.http.exceptions import DefaultBackoffException
from conftest import find_stream
from source_snapchat_marketing.source import SourceSnapchatMarketing
logger = logging.getLogger("airbyte_logger")
config_mock = {
"authenticator": NoAuth(),
"start_date": "2000-01-01",
"end_date": "2000-02-10",
"client_id": "client_id",
"client_secret": "client_secret",
"refresh_token": "refresh_token",
"start_date": "2024-01-01",
"end_date": "2024-02-10",
"action_report_time": "impression",
"swipe_up_attribution_window": "7_DAY",
"view_attribution_window": "1_DAY",
}
stats_stream = AdaccountsStatsDaily(**config_mock)
@pytest.mark.parametrize(
"slice_period,expected_date_slices",
[
# for Hourly streams
(
7,
[
{"start_time": "2000-01-01", "end_time": "2000-01-08"},
{"start_time": "2000-01-08", "end_time": "2000-01-15"},
{"start_time": "2000-01-15", "end_time": "2000-01-22"},
{"start_time": "2000-01-22", "end_time": "2000-01-29"},
{"start_time": "2000-01-29", "end_time": "2000-02-05"},
{"start_time": "2000-02-05", "end_time": "2000-02-10"},
],
),
# for Daily streams
(
31,
[
{"start_time": "2000-01-01", "end_time": "2000-02-01"},
{"start_time": "2000-02-01", "end_time": "2000-02-10"},
],
),
# when start-end period == slice period
(
40,
[
{"start_time": "2000-01-01", "end_time": "2000-02-10"},
],
),
# when start-end period > slice period
(
100,
[
{"start_time": "2000-01-01", "end_time": "2000-02-10"},
],
),
],
)
def test_date_slices(slice_period, expected_date_slices):
stats_stream.slice_period = slice_period
date_slices = stats_stream.date_slices()
assert date_slices == expected_date_slices
response_organizations = {
"organizations": [
{
"organization": {
"id": "organization_id_1",
"updated_at": "2020-12-15T22:35:17.819Z",
"created_at": "2020-12-15T11:13:03.910Z",
"updated_at": "2024-02-05T22:35:17.819Z",
"created_at": "2024-02-05T11:13:03.910Z",
}
}
]
}
def test_organizations(requests_mock):
def test_should_retry_403_error(requests_mock):
requests_mock.post("https://accounts.snapchat.com/login/oauth2/access_token", json={"access_token": "XXX", "expires_in": 3600})
requests_mock.register_uri(
"GET", "https://adsapi.snapchat.com/v1/me/organizations", [{"status_code": 403, "json": {"organizations": []}}]
)
stream = find_stream("organizations", config_mock)
with pytest.raises(DefaultBackoffException):
list(stream.read_records(sync_mode=SyncMode.full_refresh))
def test_organizations(requests_mock):
requests_mock.post("https://accounts.snapchat.com/login/oauth2/access_token", json={"access_token": "XXX", "expires_in": 3600})
requests_mock.get("https://adsapi.snapchat.com/v1/me/organizations", json=response_organizations)
stream = Organizations(**config_mock)
records = stream.read_records(sync_mode=SyncMode.full_refresh)
assert list(records) == [
{
"id": "organization_id_1",
"updated_at": "2020-12-15T22:35:17.819Z",
"created_at": "2020-12-15T11:13:03.910Z",
}
]
stream = find_stream("organizations", config_mock)
records = stream.read_records(sync_mode=SyncMode.full_refresh, stream_slice=StreamSlice(partition={},
cursor_slice={"start_time": "2024-01-01",
"end_time": "2024-01-01"}),
stream_state=None)
assert json.dumps(next(records).data, sort_keys=True) == json.dumps(
{"id": "organization_id_1", "updated_at": "2024-02-05T22:35:17.819Z", "created_at": "2024-02-05T11:13:03.910Z"}, sort_keys=True)
response_adaccounts = {
@@ -107,15 +65,15 @@ response_adaccounts = {
{
"adaccount": {
"id": "adaccount_id_1",
"updated_at": "2020-12-15T22:35:17.819Z",
"created_at": "2020-12-15T11:13:03.910Z",
"updated_at": "2024-02-05T22:35:17.819Z",
"created_at": "2024-02-05T11:13:03.910Z",
}
},
{
"adaccount": {
"id": "adaccount_id_2",
"updated_at": "2020-12-15T22:35:17.819Z",
"created_at": "2020-12-15T11:13:03.910Z",
"updated_at": "2024-02-05T22:35:17.819Z",
"created_at": "2024-02-05T11:13:03.910Z",
}
},
]
@@ -129,22 +87,24 @@ def run_stream(stream):
def test_accounts(requests_mock):
requests_mock.post("https://accounts.snapchat.com/login/oauth2/access_token", json={"access_token": "XXX", "expires_in": 3600})
requests_mock.get("https://adsapi.snapchat.com/v1/me/organizations", json=response_organizations)
requests_mock.get("https://adsapi.snapchat.com/v1/organizations/organization_id_1/adaccounts", json=response_adaccounts)
stream = Adaccounts(**config_mock)
stream = find_stream("adaccounts", config_mock)
records = run_stream(stream)
assert list(records) == [
list_records = [record.data for record in records]
assert list_records == [
{
"id": "adaccount_id_1",
"updated_at": "2020-12-15T22:35:17.819Z",
"created_at": "2020-12-15T11:13:03.910Z",
"updated_at": "2024-02-05T22:35:17.819Z",
"created_at": "2024-02-05T11:13:03.910Z",
},
{
"id": "adaccount_id_2",
"updated_at": "2020-12-15T22:35:17.819Z",
"created_at": "2020-12-15T11:13:03.910Z",
"updated_at": "2024-02-05T22:35:17.819Z",
"created_at": "2024-02-05T11:13:03.910Z",
},
]
@@ -154,15 +114,15 @@ response_ads = {
{
"ad": {
"id": "ad_id_1",
"updated_at": "2020-12-15T22:35:17.819Z",
"created_at": "2020-12-15T11:13:03.910Z",
"updated_at": "2024-02-05T22:35:17.819Z",
"created_at": "2024-02-05T11:13:03.910Z",
}
},
{
"ad": {
"id": "ad_id_2",
"updated_at": "2020-12-15T22:35:17.819Z",
"created_at": "2020-12-15T11:13:03.910Z",
"updated_at": "2024-02-05T22:35:17.819Z",
"created_at": "2024-02-05T11:13:03.910Z",
}
},
]
@@ -170,24 +130,26 @@ response_ads = {
def test_ads(requests_mock):
requests_mock.post("https://accounts.snapchat.com/login/oauth2/access_token", json={"access_token": "XXX", "expires_in": 3600})
requests_mock.get("https://adsapi.snapchat.com/v1/me/organizations", json=response_organizations)
requests_mock.get("https://adsapi.snapchat.com/v1/organizations/organization_id_1/adaccounts", json=response_adaccounts)
requests_mock.get("https://adsapi.snapchat.com/v1/adaccounts/adaccount_id_1/ads", json={"ads": []})
requests_mock.get("https://adsapi.snapchat.com/v1/adaccounts/adaccount_id_2/ads", json=response_ads)
stream = Ads(**config_mock)
stream = find_stream("ads", config_mock)
records = run_stream(stream)
assert list(records) == [
list_records = [record.data for record in records]
assert list_records == [
{
"id": "ad_id_1",
"updated_at": "2020-12-15T22:35:17.819Z",
"created_at": "2020-12-15T11:13:03.910Z",
"updated_at": "2024-02-05T22:35:17.819Z",
"created_at": "2024-02-05T11:13:03.910Z",
},
{
"id": "ad_id_2",
"updated_at": "2020-12-15T22:35:17.819Z",
"created_at": "2020-12-15T11:13:03.910Z",
"updated_at": "2024-02-05T22:35:17.819Z",
"created_at": "2024-02-05T11:13:03.910Z",
},
]
@@ -215,7 +177,6 @@ response_ads_stats_lifetime_1 = {
],
}
response_ads_stats_lifetime_2 = {
"request_status": "SUCCESS",
"request_id": "d0cb395f-c39d-480d-b62c-24878c7d0b76",
@@ -241,6 +202,7 @@ response_ads_stats_lifetime_2 = {
def test_ads_stats_lifetime(requests_mock):
requests_mock.post("https://accounts.snapchat.com/login/oauth2/access_token", json={"access_token": "XXX", "expires_in": 3600})
requests_mock.get("https://adsapi.snapchat.com/v1/me/organizations", json=response_organizations)
requests_mock.get("https://adsapi.snapchat.com/v1/organizations/organization_id_1/adaccounts", json=response_adaccounts)
@@ -249,31 +211,166 @@ def test_ads_stats_lifetime(requests_mock):
requests_mock.get("https://adsapi.snapchat.com/v1/ads/ad_id_1/stats", json=response_ads_stats_lifetime_1)
requests_mock.get("https://adsapi.snapchat.com/v1/ads/ad_id_2/stats", json=response_ads_stats_lifetime_2)
stream = AdsStatsLifetime(**config_mock)
stream = find_stream("ads_stats_lifetime", config_mock)
records = run_stream(stream)
assert list(records) == [
list_records = [record.data for record in records]
assert list_records == [
{
"conversion_data_processed_end_time": "2022-07-01T00:00:00.000Z",
"end_time": "2022-07-01T07:00:00.000-07:00",
"finalized_data_end_time": "2022-07-01T07:00:00.000-07:00",
"granularity": "LIFETIME",
"id": "ad_id_1",
"impressions": 0,
"start_time": "2016-09-26T00:00:00.000-07:00",
"swipes": 0,
"type": "AD",
},
{
"conversion_data_processed_end_time": "2022-07-01T00:00:00.000Z",
"granularity": "LIFETIME",
"start_time": "2016-09-26T00:00:00.000-07:00",
"end_time": "2022-07-01T07:00:00.000-07:00",
"finalized_data_end_time": "2022-07-01T07:00:00.000-07:00",
"granularity": "LIFETIME",
"id": "ad_id_2",
"conversion_data_processed_end_time": "2022-07-01T00:00:00.000Z",
"android_installs": None,
"attachment_avg_view_time_millis": None,
"attachment_impressions": None,
"attachment_quartile_1": None,
"attachment_quartile_2": None,
"attachment_quartile_3": None,
"attachment_total_view_time_millis": None,
"attachment_view_completion": None,
"avg_screen_time_millis": None,
"avg_view_time_millis": None,
"impressions": 0,
"start_time": "2016-09-26T00:00:00.000-07:00",
"ios_installs": None,
"quartile_1": None,
"quartile_2": None,
"quartile_3": None,
"screen_time_millis": None,
"swipe_up_percent": None,
"swipes": 0,
"type": "AD",
"total_installs": None,
"video_views": None,
"video_views_time_based": None,
"video_views_15s": None,
"view_completion": None,
"view_time_millis": None,
"paid_impressions": None,
"earned_impressions": None,
"total_impressions": None,
"play_time_millis": None,
"shares": None,
"saves": None,
"native_leads": None,
"conversion_purchases": None,
"conversion_purchases_value": None,
"conversion_save": None,
"conversion_start_checkout": None,
"conversion_add_cart": None,
"conversion_view_content": None,
"conversion_add_billing": None,
"conversion_searches": None,
"conversion_level_completes": None,
"conversion_app_opens": None,
"conversion_page_views": None,
"conversion_subscribe": None,
"conversion_ad_click": None,
"conversion_ad_view": None,
"conversion_complete_tutorial": None,
"conversion_invite": None,
"conversion_login": None,
"conversion_share": None,
"conversion_reserve": None,
"conversion_achievement_unlocked": None,
"conversion_add_to_wishlist": None,
"conversion_spend_credits": None,
"conversion_rate": None,
"conversion_start_trial": None,
"conversion_list_view": None,
"custom_event_1": None,
"custom_event_2": None,
"custom_event_3": None,
"custom_event_4": None,
"custom_event_5": None,
"story_opens": None,
"story_completes": None,
"attachment_frequency": None,
"attachment_uniques": None,
"frequency": None,
"uniques": None,
"total_reach": None,
"earned_reach": None
},
{
"id": "ad_id_2",
"type": "AD",
"granularity": "LIFETIME",
"start_time": "2016-09-26T00:00:00.000-07:00",
"end_time": "2022-07-01T07:00:00.000-07:00",
"finalized_data_end_time": "2022-07-01T07:00:00.000-07:00",
"conversion_data_processed_end_time": "2022-07-01T00:00:00.000Z",
"android_installs": None,
"attachment_avg_view_time_millis": None,
"attachment_impressions": None,
"attachment_quartile_1": None,
"attachment_quartile_2": None,
"attachment_quartile_3": None,
"attachment_total_view_time_millis": None,
"attachment_view_completion": None,
"avg_screen_time_millis": None,
"avg_view_time_millis": None,
"impressions": 0,
"ios_installs": None,
"quartile_1": None,
"quartile_2": None,
"quartile_3": None,
"screen_time_millis": None,
"swipe_up_percent": None,
"swipes": 0,
"total_installs": None,
"video_views": None,
"video_views_time_based": None,
"video_views_15s": None,
"view_completion": None,
"view_time_millis": None,
"paid_impressions": None,
"earned_impressions": None,
"total_impressions": None,
"play_time_millis": None,
"shares": None,
"saves": None,
"native_leads": None,
"conversion_purchases": None,
"conversion_purchases_value": None,
"conversion_save": None,
"conversion_start_checkout": None,
"conversion_add_cart": None,
"conversion_view_content": None,
"conversion_add_billing": None,
"conversion_searches": None,
"conversion_level_completes": None,
"conversion_app_opens": None,
"conversion_page_views": None,
"conversion_subscribe": None,
"conversion_ad_click": None,
"conversion_ad_view": None,
"conversion_complete_tutorial": None,
"conversion_invite": None,
"conversion_login": None,
"conversion_share": None,
"conversion_reserve": None,
"conversion_achievement_unlocked": None,
"conversion_add_to_wishlist": None,
"conversion_spend_credits": None,
"conversion_rate": None,
"conversion_start_trial": None,
"conversion_list_view": None,
"custom_event_1": None,
"custom_event_2": None,
"custom_event_3": None,
"custom_event_4": None,
"custom_event_5": None,
"story_opens": None,
"story_completes": None,
"attachment_frequency": None,
"attachment_uniques": None,
"frequency": None,
"uniques": None,
"total_reach": None,
"earned_reach": None
}
]
@@ -287,14 +384,14 @@ response_ads_stats_daily_1 = {
"id": "417d0269-80fb-496a-b5f3-ec0bac665144",
"type": "AD",
"granularity": "DAY",
"start_time": "2022-06-25T00:00:00.000-07:00",
"end_time": "2022-06-29T00:00:00.000-07:00",
"start_time": "2024-02-05T00:00:00.000-07:00",
"end_time": "2024-02-08T00:00:00.000-07:00",
"finalized_data_end_time": "2022-06-30T00:00:00.000-07:00",
"conversion_data_processed_end_time": "2022-06-30T00:00:00.000Z",
"timeseries": [
{
"start_time": "2022-06-25T00:00:00.000-07:00",
"end_time": "2022-06-26T00:00:00.000-07:00",
"start_time": "2024-02-05T00:00:00.000-07:00",
"end_time": "2024-02-06T00:00:00.000-07:00",
"stats": {
"impressions": 0,
"swipes": 0,
@@ -304,8 +401,8 @@ response_ads_stats_daily_1 = {
},
},
{
"start_time": "2022-06-26T00:00:00.000-07:00",
"end_time": "2022-06-27T00:00:00.000-07:00",
"start_time": "2024-02-07T00:00:00.000-07:00",
"end_time": "2024-02-08T00:00:00.000-07:00",
"stats": {
"impressions": 0,
"swipes": 0,
@@ -322,6 +419,7 @@ response_ads_stats_daily_1 = {
def test_ads_stats_daily(requests_mock):
requests_mock.post("https://accounts.snapchat.com/login/oauth2/access_token", json={"access_token": "XXX", "expires_in": 3600})
requests_mock.get("https://adsapi.snapchat.com/v1/me/organizations", json=response_organizations)
requests_mock.get("https://adsapi.snapchat.com/v1/organizations/organization_id_1/adaccounts", json=response_adaccounts)
@@ -330,36 +428,11 @@ def test_ads_stats_daily(requests_mock):
requests_mock.get("https://adsapi.snapchat.com/v1/ads/ad_id_1/stats", json={"timeseries_stats": []})
requests_mock.get("https://adsapi.snapchat.com/v1/ads/ad_id_2/stats", json=response_ads_stats_daily_1)
stream = AdsStatsDaily(**config_mock)
stream = find_stream("ads_stats_daily", config_mock)
records = run_stream(stream)
assert len(list(records)) == 4 # 2 records for each of 2 slices
def test_get_parent_ids(requests_mock):
"""Test cache usage in get_parent_ids"""
# nonlocal auxiliary_id_map
requests_mock.get("https://adsapi.snapchat.com/v1/me/organizations", json=response_organizations)
requests_mock.get("https://adsapi.snapchat.com/v1/organizations/organization_id_1/adaccounts", json=response_adaccounts)
stream = Adaccounts(**config_mock)
# reset cache, it can be filled by calls in previous tests
source_snapchat_marketing.source.auxiliary_id_map = {}
# 1st call
list(run_stream(stream))
# 1st request to organizations
# 2nd request to adaccounts
assert len(requests_mock.request_history) == 2
# 2nd call
list(run_stream(stream))
# request to organizations is skipped due to cache
# 3rd request to adaccounts
assert len(requests_mock.request_history) == 3
def test_source_streams():
source_config = {"client_id": "XXX", "client_secret": "XXX", "refresh_token": "XXX", "start_date": "2022-05-25"}
streams = SourceSnapchatMarketing().streams(config=source_config)
@@ -369,34 +442,7 @@ def test_source_streams():
def test_source_check_connection(requests_mock):
source_config = {"client_id": "XXX", "client_secret": "XXX", "refresh_token": "XXX", "start_date": "2022-05-25"}
requests_mock.post("https://accounts.snapchat.com/login/oauth2/access_token", json={"access_token": "XXX", "expires_in": 3600})
requests_mock.get("https://adsapi.snapchat.com/v1/me", json={})
requests_mock.get("https://adsapi.snapchat.com/v1/me/organizations", json={})
results = SourceSnapchatMarketing().check_connection(logger=None, config=source_config)
results = SourceSnapchatMarketing().check_connection(logger=logger, config=source_config)
assert results == (True, None)
def test_retry_get_access_token(requests_mock):
requests_mock.register_uri(
"POST",
"https://accounts.snapchat.com/login/oauth2/access_token",
[{"status_code": 429}, {"status_code": 429}, {"status_code": 200, "json": {"access_token": "token", "expires_in": 3600}}],
)
auth = Oauth2Authenticator(
token_refresh_endpoint="https://accounts.snapchat.com/login/oauth2/access_token",
client_id="client_id",
client_secret="client_secret",
refresh_token="refresh_token",
)
token = auth.get_access_token()
assert len(requests_mock.request_history) == 3
assert token == "token"
def test_should_retry_403_error(requests_mock):
requests_mock.register_uri(
"GET", "https://adsapi.snapchat.com/v1/me/organizations", [{"status_code": 403, "json": {"organizations": []}}]
)
stream = Organizations(**config_mock)
records = list(stream.read_records(sync_mode=SyncMode.full_refresh))
assert not records

View File

@@ -0,0 +1,27 @@
# Snapchat Marketing Migration Guide
## Upgrading to 1.0.0
We're continuously striving to enhance the quality and reliability of our connectors at Airbyte.
As part of our commitment to delivering exceptional service, we are transitioning Snapchat Marketing source from
the Python Connector Development Kit (CDK) to our innovative low-code framework. This is part of a strategic move
to streamline many processes across connectors, bolstering maintainability and freeing us to focus more of our efforts
on improving the performance and features of our evolving platform and growing catalog. However, due to differences
between the Python and low-code CDKs, this migration constitutes a breaking change.
To gracefully handle these changes for your existing connections, we highly recommend resetting your data before resuming your data syncs with the new version.
### Migration Steps
1. Select **Connections** in the main navbar.
1. Select the connection(s) affected by the update.
2. Select the **Schema** tab.
3. Uncheck all streams except the affected ones.
4. Select **Save changes** at the bottom of the page.
5. Select the **Settings** tab.
6. Press the **Clear your data** button.
7. Return to the **Schema** tab.
8. Check all your streams.
9. Select **Sync now** to sync your data
For more information on resetting your data in Airbyte, see [this page](/operator-guides/clear).

View File

@@ -89,14 +89,14 @@ This page guides you through the process of setting up the Snapchat Marketing so
## Supported streams and sync modes
| Stream | Incremental | Key |
| :---------------------- | :---------- | ----------------------------------- |
|:------------------------|:------------|-------------------------------------|
| Adaccounts | Yes | "id" |
| Ads | Yes | "id" |
| Adsquads | Yes | "id" |
| Campaigns | Yes | "id" |
| Creatives | Yes | "id" |
| Media | Yes | "id" |
| Organizations | No | "id" |
| Organizations | Yes | "id" |
| Segments | Yes | "id" |
| AdaccountsStatsHourly | Yes | ["id", "granularity", "start_time"] |
| AdaccountsStatsDaily | Yes | ["id", "granularity", "start_time"] |
@@ -123,8 +123,9 @@ Snapchat Marketing API has limitations to 1000 items per page.
<summary>Expand to review</summary>
| Version | Date | Pull Request | Subject |
| :------ | :--------- | :------------------------------------------------------- | :----------------------------------------------------------------------------- |
| 0.6.2 | 2024-15-22 | [38574](https://github.com/airbytehq/airbyte/pull/38574) | Update authenticator package |
|:--------|:-----------|:---------------------------------------------------------|:-------------------------------------------------------------------------------|
| 1.0.0 | 2024-06-20 | [39507](https://github.com/airbytehq/airbyte/pull/39507) | Migrate to low-code CDK and add incremental functionality to `organizations` |
| 0.6.2 | 2024-05-22 | [38574](https://github.com/airbytehq/airbyte/pull/38574) | Update authenticator package |
| 0.6.1 | 2024-04-24 | [36662](https://github.com/airbytehq/airbyte/pull/36662) | Schema descriptions |
| 0.6.0 | 2024-04-10 | [30586](https://github.com/airbytehq/airbyte/pull/30586) | Add `attribution_windows`,`action_report_time` as optional configurable params |
| 0.5.0 | 2024-03-19 | [36267](https://github.com/airbytehq/airbyte/pull/36267) | Pin airbyte-cdk version to `^0` |