diff --git a/airbyte-config/init/src/main/resources/seed/source_definitions.yaml b/airbyte-config/init/src/main/resources/seed/source_definitions.yaml
index ee2395a9c285..2938c31fa517 100644
--- a/airbyte-config/init/src/main/resources/seed/source_definitions.yaml
+++ b/airbyte-config/init/src/main/resources/seed/source_definitions.yaml
@@ -944,7 +944,7 @@
- name: Stripe
sourceDefinitionId: e094cb9a-26de-4645-8761-65c0c425d1de
dockerRepository: airbyte/source-stripe
- dockerImageTag: 0.1.35
+ dockerImageTag: 0.1.36
documentationUrl: https://docs.airbyte.io/integrations/sources/stripe
icon: stripe.svg
sourceType: api
diff --git a/airbyte-config/init/src/main/resources/seed/source_specs.yaml b/airbyte-config/init/src/main/resources/seed/source_specs.yaml
index 4c45cc95ad2c..7feb0c732640 100644
--- a/airbyte-config/init/src/main/resources/seed/source_specs.yaml
+++ b/airbyte-config/init/src/main/resources/seed/source_specs.yaml
@@ -9345,7 +9345,7 @@
type: "string"
path_in_connector_config:
- "client_secret"
-- dockerImage: "airbyte/source-stripe:0.1.35"
+- dockerImage: "airbyte/source-stripe:0.1.36"
spec:
documentationUrl: "https://docs.airbyte.io/integrations/sources/stripe"
connectionSpecification:
@@ -9389,6 +9389,23 @@
\ is frequently updated after creation. More info here"
order: 3
+ slice_range:
+ type: "integer"
+ title: "Data request time increment in days (Optional)"
+ default: 365
+ minimum: 1
+ examples:
+ - 1
+ - 3
+ - 10
+ - 30
+ - 180
+ - 360
+ description: "The time increment used by the connector when requesting data\
+ \ from the Stripe API. The bigger the value is, the less requests will\
+ \ be made and faster the sync will be. On the other hand, the more seldom\
+ \ the state is persisted."
+ order: 4
supportsNormalization: false
supportsDBT: false
supported_destination_sync_modes: []
diff --git a/airbyte-integrations/connectors/source-stripe/Dockerfile b/airbyte-integrations/connectors/source-stripe/Dockerfile
index 0dcc64e056e4..11d615ac8c77 100644
--- a/airbyte-integrations/connectors/source-stripe/Dockerfile
+++ b/airbyte-integrations/connectors/source-stripe/Dockerfile
@@ -4,13 +4,13 @@ FROM python:3.9-slim
RUN apt-get update && apt-get install -y bash && rm -rf /var/lib/apt/lists/*
WORKDIR /airbyte/integration_code
-COPY source_stripe ./source_stripe
-COPY main.py ./
COPY setup.py ./
RUN pip install .
+COPY source_stripe ./source_stripe
+COPY main.py ./
ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py"
ENTRYPOINT ["python", "/airbyte/integration_code/main.py"]
-LABEL io.airbyte.version=0.1.35
+LABEL io.airbyte.version=0.1.36
LABEL io.airbyte.name=airbyte/source-stripe
diff --git a/airbyte-integrations/connectors/source-stripe/integration_tests/abnormal_state.json b/airbyte-integrations/connectors/source-stripe/integration_tests/abnormal_state.json
index 168cd531425f..aac5fd711ab0 100644
--- a/airbyte-integrations/connectors/source-stripe/integration_tests/abnormal_state.json
+++ b/airbyte-integrations/connectors/source-stripe/integration_tests/abnormal_state.json
@@ -1,20 +1,20 @@
{
- "charges": { "created": 161703040300 },
- "coupons": { "created": 161703040300 },
- "events": { "created": 161749384700 },
- "customers": { "created": 160083796900 },
- "plans": { "created": 159484835000 },
- "invoices": { "created": 161749017500 },
- "invoice_items": { "date": 159494698100 },
- "transfers": { "created": 161099582400 },
- "subscriptions": { "created": 159968687300 },
- "balance_transactions": { "created": 161706755600 },
- "payouts": { "created": 161706755600 },
- "disputes": { "created": 161099630500 },
- "products": { "created": 158551134100 },
- "refunds": { "created": 161959562900 },
- "payment_intents": { "created": 161959562900 },
- "promotion_codes": { "created": 163534157100 },
+ "charges": { "created": 10000000000 },
+ "coupons": { "created": 10000000000 },
+ "events": { "created": 10000000000 },
+ "customers": { "created": 10000000000 },
+ "plans": { "created": 10000000000 },
+ "invoices": { "created": 10000000000 },
+ "invoice_items": { "date": 10000000000 },
+ "transfers": { "created": 10000000000 },
+ "subscriptions": { "created": 10000000000 },
+ "balance_transactions": { "created": 10000000000 },
+ "payouts": { "created": 10000000000 },
+ "disputes": { "created": 10000000000 },
+ "products": { "created": 10000000000 },
+ "refunds": { "created": 10000000000 },
+ "payment_intents": { "created": 10000000000 },
+ "promotion_codes": { "created": 10000000000 },
"checkout_sessions": { "expires_at": 10000000000 },
"checkout_sessions_line_items": { "checkout_session_expires_at": 10000000000 }
}
diff --git a/airbyte-integrations/connectors/source-stripe/integration_tests/test_dummy.py b/airbyte-integrations/connectors/source-stripe/integration_tests/test_dummy.py
deleted file mode 100644
index f1f977513d63..000000000000
--- a/airbyte-integrations/connectors/source-stripe/integration_tests/test_dummy.py
+++ /dev/null
@@ -1,10 +0,0 @@
-#
-# Copyright (c) 2022 Airbyte, Inc., all rights reserved.
-#
-
-
-def test_dummy():
- """
- Dummy test to prevent gradle from failing test for this connector
- """
- assert True
diff --git a/airbyte-integrations/connectors/source-stripe/setup.py b/airbyte-integrations/connectors/source-stripe/setup.py
index 0b8de104dc9c..492dfc4e5c92 100644
--- a/airbyte-integrations/connectors/source-stripe/setup.py
+++ b/airbyte-integrations/connectors/source-stripe/setup.py
@@ -5,7 +5,7 @@
from setuptools import find_packages, setup
-MAIN_REQUIREMENTS = ["airbyte-cdk~=0.1", "stripe==2.56.0", "pendulum==1.2.0"]
+MAIN_REQUIREMENTS = ["airbyte-cdk~=0.1", "stripe==2.56.0", "pendulum==2.1.2"]
TEST_REQUIREMENTS = [
"pytest~=6.1",
diff --git a/airbyte-integrations/connectors/source-stripe/source_stripe/source.py b/airbyte-integrations/connectors/source-stripe/source_stripe/source.py
index a3a8835627a4..1d5dd91396b8 100644
--- a/airbyte-integrations/connectors/source-stripe/source_stripe/source.py
+++ b/airbyte-integrations/connectors/source-stripe/source_stripe/source.py
@@ -51,7 +51,12 @@ def check_connection(self, logger: AirbyteLogger, config: Mapping[str, Any]) ->
def streams(self, config: Mapping[str, Any]) -> List[Stream]:
authenticator = TokenAuthenticator(config["client_secret"])
start_date = pendulum.parse(config["start_date"]).int_timestamp
- args = {"authenticator": authenticator, "account_id": config["account_id"], "start_date": start_date}
+ args = {
+ "authenticator": authenticator,
+ "account_id": config["account_id"],
+ "start_date": start_date,
+ "slice_range": config.get("slice_range"),
+ }
incremental_args = {**args, "lookback_window_days": config.get("lookback_window_days")}
return [
BalanceTransactions(**incremental_args),
diff --git a/airbyte-integrations/connectors/source-stripe/source_stripe/spec.yaml b/airbyte-integrations/connectors/source-stripe/source_stripe/spec.yaml
index 20c01267898d..1baa105033d2 100644
--- a/airbyte-integrations/connectors/source-stripe/source_stripe/spec.yaml
+++ b/airbyte-integrations/connectors/source-stripe/source_stripe/spec.yaml
@@ -44,3 +44,14 @@ connectionSpecification:
after creation. More info here
order: 3
+ slice_range:
+ type: integer
+ title: Data request time increment in days (Optional)
+ default: 365
+ minimum: 1
+ examples: [1, 3, 10, 30, 180, 360]
+ description: >-
+ The time increment used by the connector when requesting data from the Stripe API. The bigger the value is,
+ the less requests will be made and faster the sync will be. On the other hand, the more seldom
+ the state is persisted.
+ order: 4
diff --git a/airbyte-integrations/connectors/source-stripe/source_stripe/streams.py b/airbyte-integrations/connectors/source-stripe/source_stripe/streams.py
index 5fc5e1efd2c3..a6023fb37dac 100644
--- a/airbyte-integrations/connectors/source-stripe/source_stripe/streams.py
+++ b/airbyte-integrations/connectors/source-stripe/source_stripe/streams.py
@@ -5,7 +5,7 @@
import math
from abc import ABC, abstractmethod
from itertools import chain
-from typing import Any, Iterable, Mapping, MutableMapping, Optional
+from typing import Any, Iterable, List, Mapping, MutableMapping, Optional, Tuple
import pendulum
import requests
@@ -16,11 +16,13 @@
class StripeStream(HttpStream, ABC):
url_base = "https://api.stripe.com/v1/"
primary_key = "id"
+ DEFAULT_SLICE_RANGE = 365
- def __init__(self, start_date: int, account_id: str, **kwargs):
+ def __init__(self, start_date: int, account_id: str, slice_range: int = DEFAULT_SLICE_RANGE, **kwargs):
super().__init__(**kwargs)
self.account_id = account_id
self.start_date = start_date
+ self.slice_range = slice_range or self.DEFAULT_SLICE_RANGE
def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]:
decoded_response = response.json()
@@ -37,6 +39,9 @@ def request_params(
# Stripe default pagination is 10, max is 100
params = {"limit": 100}
+ for key in ("created[gte]", "created[lte]"):
+ if key in stream_slice:
+ params[key] = stream_slice[key]
# Handle pagination by inserting the next page's token in the request parameters
if next_page_token:
@@ -54,6 +59,28 @@ def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapp
response_json = response.json()
yield from response_json.get("data", []) # Stripe puts records in a container array "data"
+ def chunk_dates(self, start_date_ts: int) -> Iterable[Tuple[int, int]]:
+ now = pendulum.now().int_timestamp
+ step = int(pendulum.duration(days=self.slice_range).total_seconds())
+ after_ts = start_date_ts
+ while after_ts < now:
+ before_ts = min(now, after_ts + step)
+ yield after_ts, before_ts
+ after_ts = before_ts + 1
+
+ def stream_slices(
+ self, *, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None
+ ) -> Iterable[Optional[Mapping[str, Any]]]:
+ for start, end in self.chunk_dates(self.start_date):
+ yield {"created[gte]": start, "created[lte]": end}
+
+
+class SingleEmptySliceMixin(object):
+ def stream_slices(
+ self, *, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None
+ ) -> Iterable[Optional[Mapping[str, Any]]]:
+ return [{}]
+
class IncrementalStripeStream(StripeStream, ABC):
# Stripe returns most recently created objects first, so we don't want to persist state until the entire stream has been read
@@ -79,14 +106,27 @@ def get_updated_state(self, current_stream_state: MutableMapping[str, Any], late
"""
return {self.cursor_field: max(latest_record.get(self.cursor_field), current_stream_state.get(self.cursor_field, 0))}
- def request_params(self, stream_state: Mapping[str, Any] = None, **kwargs):
- stream_state = stream_state or {}
- params = super().request_params(stream_state=stream_state, **kwargs)
-
- start_timestamp = self.get_start_timestamp(stream_state)
- if start_timestamp:
- params["created[gte]"] = start_timestamp
- return params
+ def read_records(
+ self,
+ sync_mode: SyncMode,
+ cursor_field: List[str] = None,
+ stream_slice: Mapping[str, Any] = None,
+ stream_state: Mapping[str, Any] = None,
+ ) -> Iterable[Mapping[str, Any]]:
+ if stream_slice is None:
+ return []
+ yield from super().read_records(sync_mode, cursor_field, stream_slice, stream_state)
+
+ def stream_slices(
+ self, *, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None
+ ) -> Iterable[Optional[Mapping[str, Any]]]:
+ start_ts = self.get_start_timestamp(stream_state)
+ if start_ts >= pendulum.now().int_timestamp:
+ # if the state is in the future - this will produce a state message but not make an API request
+ yield None
+ else:
+ for start, end in self.chunk_dates(start_ts):
+ yield {"created[gte]": start, "created[lte]": end}
def get_start_timestamp(self, stream_state) -> int:
start_point = self.start_date
@@ -134,7 +174,7 @@ def path(self, **kwargs) -> str:
return "charges"
-class CustomerBalanceTransactions(StripeStream):
+class CustomerBalanceTransactions(SingleEmptySliceMixin, StripeStream):
"""
API docs: https://stripe.com/docs/api/customer_balance_transactions/list
"""
@@ -147,8 +187,10 @@ def path(self, stream_slice: Mapping[str, Any] = None, **kwargs):
def read_records(self, stream_slice: Optional[Mapping[str, Any]] = None, **kwargs) -> Iterable[Mapping[str, Any]]:
customers_stream = Customers(authenticator=self.authenticator, account_id=self.account_id, start_date=self.start_date)
- for customer in customers_stream.read_records(sync_mode=SyncMode.full_refresh):
- yield from super().read_records(stream_slice={"customer_id": customer["id"]}, **kwargs)
+ slices = customers_stream.stream_slices(sync_mode=SyncMode.full_refresh)
+ for _slice in slices:
+ for customer in customers_stream.read_records(sync_mode=SyncMode.full_refresh, stream_slice=_slice):
+ yield from super().read_records(stream_slice={"customer_id": customer["id"]}, **kwargs)
class Coupons(IncrementalStripeStream):
@@ -184,7 +226,7 @@ def path(self, **kwargs):
return "events"
-class StripeSubStream(StripeStream, ABC):
+class StripeSubStream(SingleEmptySliceMixin, StripeStream, ABC):
"""
Research shows that records related to SubStream can be extracted from Parent streams which already
contain 1st page of needed items. Thus, it significantly decreases a number of requests needed to get
@@ -261,31 +303,32 @@ def request_params(self, stream_slice: Mapping[str, Any] = None, **kwargs):
return params
def read_records(self, sync_mode: SyncMode, stream_slice: Optional[Mapping[str, Any]] = None, **kwargs) -> Iterable[Mapping[str, Any]]:
-
parent_stream = self.parent(authenticator=self.authenticator, account_id=self.account_id, start_date=self.start_date)
- for record in parent_stream.read_records(sync_mode=SyncMode.full_refresh):
+ slices = parent_stream.stream_slices(sync_mode=SyncMode.full_refresh)
+ for _slice in slices:
+ for record in parent_stream.read_records(sync_mode=SyncMode.full_refresh, stream_slice=_slice):
- items_obj = record.get(self.sub_items_attr, {})
- if not items_obj:
- continue
+ items_obj = record.get(self.sub_items_attr, {})
+ if not items_obj:
+ continue
- items = items_obj.get("data", [])
+ items = items_obj.get("data", [])
- # non-generic filter, mainly for BankAccounts stream only
- if self.filter:
- items = [i for i in items if i.get(self.filter["attr"]) == self.filter["value"]]
+ # non-generic filter, mainly for BankAccounts stream only
+ if self.filter:
+ items = [i for i in items if i.get(self.filter["attr"]) == self.filter["value"]]
- # get next pages
- items_next_pages = []
- if items_obj.get("has_more") and items:
- stream_slice = {self.parent_id: record["id"], "starting_after": items[-1]["id"]}
- items_next_pages = super().read_records(sync_mode=SyncMode.full_refresh, stream_slice=stream_slice, **kwargs)
+ # get next pages
+ items_next_pages = []
+ if items_obj.get("has_more") and items:
+ stream_slice = {self.parent_id: record["id"], "starting_after": items[-1]["id"]}
+ items_next_pages = super().read_records(sync_mode=SyncMode.full_refresh, stream_slice=stream_slice, **kwargs)
- for item in chain(items, items_next_pages):
- if self.add_parent_id:
- # add reference to parent object when item doesn't have it already
- item[self.parent_id] = record["id"]
- yield item
+ for item in chain(items, items_next_pages):
+ if self.add_parent_id:
+ # add reference to parent object when item doesn't have it already
+ item[self.parent_id] = record["id"]
+ yield item
class Invoices(IncrementalStripeStream):
@@ -447,12 +490,12 @@ def path(self, stream_slice: Mapping[str, Any] = None, **kwargs):
return f"customers/{stream_slice[self.parent_id]}/sources"
def request_params(self, stream_slice: Mapping[str, Any] = None, **kwargs) -> MutableMapping[str, Any]:
- params = super().request_params(**kwargs)
+ params = super().request_params(stream_slice=stream_slice, **kwargs)
params["object"] = "bank_account"
return params
-class CheckoutSessions(IncrementalStripeStream):
+class CheckoutSessions(SingleEmptySliceMixin, IncrementalStripeStream):
"""
API docs: https://stripe.com/docs/api/checkout/sessions/list
"""
@@ -472,12 +515,6 @@ def __init__(self, **kwargs):
def path(self, **kwargs):
return "checkout/sessions"
- def request_params(self, stream_state: Mapping[str, Any] = None, **kwargs):
- params = super().request_params(stream_state=stream_state, **kwargs)
- # remove odd param, not supported by checkout_sessions api
- params.pop("created[gte]", None)
- return params
-
def parse_response(self, response: requests.Response, stream_state: Mapping[str, Any] = None, **kwargs) -> Iterable[Mapping]:
since_date = self.get_start_timestamp(stream_state)
for item in super().parse_response(response, **kwargs):
@@ -487,7 +524,7 @@ def parse_response(self, response: requests.Response, stream_state: Mapping[str,
yield item
-class CheckoutSessionsLineItems(IncrementalStripeStream):
+class CheckoutSessionsLineItems(SingleEmptySliceMixin, IncrementalStripeStream):
"""
API docs: https://stripe.com/docs/api/checkout/sessions/line_items
"""
@@ -516,7 +553,9 @@ def read_records(
if stream_state:
checkout_session_state = {"expires_at": stream_state["checkout_session_expires_at"]}
- for checkout_session in checkout_session_stream.read_records(sync_mode=SyncMode.full_refresh, stream_state=checkout_session_state):
+ for checkout_session in checkout_session_stream.read_records(
+ sync_mode=SyncMode.full_refresh, stream_state=checkout_session_state, stream_slice={}
+ ):
stream_slice = {
"checkout_session_id": checkout_session["id"],
"expires_at": checkout_session["expires_at"],
@@ -525,10 +564,6 @@ def read_records(
def request_params(self, stream_slice: Mapping[str, Any] = None, **kwargs):
params = super().request_params(stream_slice=stream_slice, **kwargs)
-
- # remove odd param, not supported by checkout_sessions api
- params.pop("created[gte]", None)
-
params["expand[]"] = ["data.discounts", "data.taxes"]
return params
@@ -545,7 +580,7 @@ def parse_response(self, response: requests.Response, stream_slice: Mapping[str,
response_json = response.json()
data = response_json.get("data", [])
if data and stream_slice:
- print(f"stream_slice: {stream_slice}")
+ self.logger.info(f"stream_slice: {stream_slice}")
cs_id = stream_slice.get("checkout_session_id", None)
cs_expires_at = stream_slice.get("expires_at", None)
for e in data:
@@ -565,7 +600,7 @@ def path(self, **kwargs):
return "promotion_codes"
-class ExternalAccount(StripeStream, ABC):
+class ExternalAccount(SingleEmptySliceMixin, StripeStream, ABC):
"""
Bank Accounts and Cards are separate streams because they have different schemas
"""
diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/test_streams.py b/airbyte-integrations/connectors/source-stripe/unit_tests/test_streams.py
index dfc6bacd71b8..b365b66c4f3f 100644
--- a/airbyte-integrations/connectors/source-stripe/unit_tests/test_streams.py
+++ b/airbyte-integrations/connectors/source-stripe/unit_tests/test_streams.py
@@ -2,6 +2,7 @@
# Copyright (c) 2022 Airbyte, Inc., all rights reserved.
#
+import pendulum
import pytest
from airbyte_cdk.models import SyncMode
from source_stripe.streams import (
@@ -128,8 +129,9 @@ def test_sub_stream(requests_mock):
"url": "/v1/invoices/in_1KD6OVIEn5WyEQxn9xuASHsD/lines",
},
)
-
- stream = InvoiceLineItems(start_date=1641008947, account_id="None")
+ # make start date a recent date so there's just one slice in a parent stream
+ start_date = pendulum.today().subtract(days=3).int_timestamp
+ stream = InvoiceLineItems(start_date=start_date, account_id="None")
records = stream.read_records(sync_mode=SyncMode.full_refresh)
assert list(records) == [
{"id": "il_1", "invoice_id": "in_1KD6OVIEn5WyEQxn9xuASHsD", "object": "line_item"},
@@ -140,7 +142,7 @@ def test_sub_stream(requests_mock):
@pytest.fixture(name="config")
def config_fixture():
- config = {"authenticator": "authenticator", "account_id": "", "start_date": 1652783086}
+ config = {"authenticator": "authenticator", "account_id": "", "start_date": 1596466368}
return config
@@ -184,16 +186,32 @@ def test_path(
@pytest.mark.parametrize(
"stream, kwargs, expected",
[
- (CustomerBalanceTransactions, {"stream_state": {}}, {"limit": 100}),
- (Customers, {}, {"created[gte]": 1652783086, "limit": 100}),
+ (
+ CustomerBalanceTransactions,
+ {"stream_state": {}, "stream_slice": {"created[gte]": 1596466368, "created[lte]": 1596552768}},
+ {"limit": 100, "created[gte]": 1596466368, "created[lte]": 1596552768},
+ ),
+ (
+ Customers,
+ {"stream_state": {}, "stream_slice": {"created[gte]": 1596466368, "created[lte]": 1596552768}},
+ {"created[gte]": 1596466368, "created[lte]": 1596552768, "limit": 100},
+ ),
(InvoiceLineItems, {"stream_state": {}, "stream_slice": {"starting_after": "2030"}}, {"limit": 100, "starting_after": "2030"}),
- (Subscriptions, {}, {"created[gte]": 1652783086, "limit": 100, "status": "all"}),
+ (
+ Subscriptions,
+ {"stream_slice": {"created[gte]": 1596466368, "created[lte]": 1596552768}},
+ {"created[gte]": 1596466368, "limit": 100, "status": "all", "created[lte]": 1596552768},
+ ),
(SubscriptionItems, {"stream_state": {}, "stream_slice": {"subscription_id": "SI"}}, {"limit": 100, "subscription": "SI"}),
(BankAccounts, {"stream_state": {}, "stream_slice": {"subscription_id": "SI"}}, {"limit": 100, "object": "bank_account"}),
- (CheckoutSessions, {"stream_state": None}, {"limit": 100}),
- (CheckoutSessionsLineItems, {"stream_state": None}, {"limit": 100, "expand[]": ["data.discounts", "data.taxes"]}),
- (ExternalAccountBankAccounts, {"stream_state": None}, {"limit": 100, "object": "bank_account"}),
- (ExternalAccountCards, {"stream_state": None}, {"limit": 100, "object": "card"}),
+ (CheckoutSessions, {"stream_state": None, "stream_slice": {}}, {"limit": 100}),
+ (
+ CheckoutSessionsLineItems,
+ {"stream_state": None, "stream_slice": {}},
+ {"limit": 100, "expand[]": ["data.discounts", "data.taxes"]},
+ ),
+ (ExternalAccountBankAccounts, {"stream_state": None, "stream_slice": {}}, {"limit": 100, "object": "bank_account"}),
+ (ExternalAccountCards, {"stream_state": None, "stream_slice": {}}, {"limit": 100, "object": "card"}),
],
)
def test_request_params(
diff --git a/docs/integrations/sources/stripe.md b/docs/integrations/sources/stripe.md
index c10eab38df34..db355a53458e 100644
--- a/docs/integrations/sources/stripe.md
+++ b/docs/integrations/sources/stripe.md
@@ -74,34 +74,35 @@ The Stripe connector should not run into Stripe API limitations under normal usa
## Changelog
-| Version | Date | Pull Request | Subject |
-|:--------|:-----------| :--- |:-------------------------------------------------------------------------------------------------------------------------------------------------------|
-| 0.1.35 | 2022-07-21 | [14924](https://github.com/airbytehq/airbyte/pull/14924) | Remove `additionalProperties` field from spec and schema |
-| 0.1.34 | 2022-07-01 | [14357](https://github.com/airbytehq/airbyte/pull/14357) | added external account streams |
+| Version | Date | Pull Request | Subject |
+|:--------|:-----------|:---------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 0.1.36 | 2022-08-04 | [15292](https://github.com/airbytehq/airbyte/pull/15292) | Implement slicing |
+| 0.1.35 | 2022-07-21 | [14924](https://github.com/airbytehq/airbyte/pull/14924) | Remove `additionalProperties` field from spec and schema |
+| 0.1.34 | 2022-07-01 | [14357](https://github.com/airbytehq/airbyte/pull/14357) | added external account streams - |
| 0.1.33 | 2022-06-06 | [13449](https://github.com/airbytehq/airbyte/pull/13449) | added semi-incremental support for CheckoutSessions and CheckoutSessionsLineItems streams, fixed big in StripeSubStream, added unittests, updated docs |
| 0.1.32 | 2022-04-30 | [12500](https://github.com/airbytehq/airbyte/pull/12500) | Improve input configuration copy |
| 0.1.31 | 2022-04-20 | [12230](https://github.com/airbytehq/airbyte/pull/12230) | Update connector to use a `spec.yaml` |
| 0.1.30 | 2022-03-21 | [11286](https://github.com/airbytehq/airbyte/pull/11286) | Minor corrections to documentation and connector specification |
| 0.1.29 | 2022-03-08 | [10359](https://github.com/airbytehq/airbyte/pull/10359) | Improved performance for streams with substreams: invoice_line_items, subscription_items, bank_accounts |
| 0.1.28 | 2022-02-08 | [10165](https://github.com/airbytehq/airbyte/pull/10165) | Improve 404 handling for `CheckoutSessionsLineItems` stream |
-| 0.1.27 | 2021-12-28 | [9148](https://github.com/airbytehq/airbyte/pull/9148) | Fix `date`, `arrival\_date` fields |
-| 0.1.26 | 2021-12-21 | [8992](https://github.com/airbytehq/airbyte/pull/8992) | Fix type `events.request` in schema |
-| 0.1.25 | 2021-11-25 | [8250](https://github.com/airbytehq/airbyte/pull/8250) | Rearrange setup fields |
-| 0.1.24 | 2021-11-08 | [7729](https://github.com/airbytehq/airbyte/pull/7729) | Include tax data in `checkout_sessions_line_items` stream |
-| 0.1.23 | 2021-11-08 | [7729](https://github.com/airbytehq/airbyte/pull/7729) | Correct `payment_intents` schema |
-| 0.1.22 | 2021-11-05 | [7345](https://github.com/airbytehq/airbyte/pull/7345) | Add 3 new streams |
-| 0.1.21 | 2021-10-07 | [6841](https://github.com/airbytehq/airbyte/pull/6841) | Fix missing `start_date` argument + update json files for SAT |
-| 0.1.20 | 2021-09-30 | [6017](https://github.com/airbytehq/airbyte/pull/6017) | Add lookback\_window\_days parameter |
-| 0.1.19 | 2021-09-27 | [6466](https://github.com/airbytehq/airbyte/pull/6466) | Use `start_date` parameter in incremental streams |
-| 0.1.18 | 2021-09-14 | [6004](https://github.com/airbytehq/airbyte/pull/6004) | Fix coupons and subscriptions stream schemas by removing incorrect timestamp formatting |
-| 0.1.17 | 2021-09-14 | [6004](https://github.com/airbytehq/airbyte/pull/6004) | Add `PaymentIntents` stream |
-| 0.1.16 | 2021-07-28 | [4980](https://github.com/airbytehq/airbyte/pull/4980) | Remove Updated field from schemas |
-| 0.1.15 | 2021-07-21 | [4878](https://github.com/airbytehq/airbyte/pull/4878) | Fix incorrect percent\_off and discounts data filed types |
-| 0.1.14 | 2021-07-09 | [4669](https://github.com/airbytehq/airbyte/pull/4669) | Subscriptions Stream now returns all kinds of subscriptions \(including expired and canceled\) |
-| 0.1.13 | 2021-07-03 | [4528](https://github.com/airbytehq/airbyte/pull/4528) | Remove regex for acc validation |
-| 0.1.12 | 2021-06-08 | [3973](https://github.com/airbytehq/airbyte/pull/3973) | Add `AIRBYTE_ENTRYPOINT` for Kubernetes support |
-| 0.1.11 | 2021-05-30 | [3744](https://github.com/airbytehq/airbyte/pull/3744) | Fix types in schema |
-| 0.1.10 | 2021-05-28 | [3728](https://github.com/airbytehq/airbyte/pull/3728) | Update data types to be number instead of int |
-| 0.1.9 | 2021-05-13 | [3367](https://github.com/airbytehq/airbyte/pull/3367) | Add acceptance tests for connected accounts |
-| 0.1.8 | 2021-05-11 | [3566](https://github.com/airbytehq/airbyte/pull/3368) | Bump CDK connectors |
+| 0.1.27 | 2021-12-28 | [9148](https://github.com/airbytehq/airbyte/pull/9148) | Fix `date`, `arrival\_date` fields |
+| 0.1.26 | 2021-12-21 | [8992](https://github.com/airbytehq/airbyte/pull/8992) | Fix type `events.request` in schema |
+| 0.1.25 | 2021-11-25 | [8250](https://github.com/airbytehq/airbyte/pull/8250) | Rearrange setup fields |
+| 0.1.24 | 2021-11-08 | [7729](https://github.com/airbytehq/airbyte/pull/7729) | Include tax data in `checkout_sessions_line_items` stream |
+| 0.1.23 | 2021-11-08 | [7729](https://github.com/airbytehq/airbyte/pull/7729) | Correct `payment_intents` schema |
+| 0.1.22 | 2021-11-05 | [7345](https://github.com/airbytehq/airbyte/pull/7345) | Add 3 new streams |
+| 0.1.21 | 2021-10-07 | [6841](https://github.com/airbytehq/airbyte/pull/6841) | Fix missing `start_date` argument + update json files for SAT |
+| 0.1.20 | 2021-09-30 | [6017](https://github.com/airbytehq/airbyte/pull/6017) | Add lookback\_window\_days parameter |
+| 0.1.19 | 2021-09-27 | [6466](https://github.com/airbytehq/airbyte/pull/6466) | Use `start_date` parameter in incremental streams |
+| 0.1.18 | 2021-09-14 | [6004](https://github.com/airbytehq/airbyte/pull/6004) | Fix coupons and subscriptions stream schemas by removing incorrect timestamp formatting |
+| 0.1.17 | 2021-09-14 | [6004](https://github.com/airbytehq/airbyte/pull/6004) | Add `PaymentIntents` stream |
+| 0.1.16 | 2021-07-28 | [4980](https://github.com/airbytehq/airbyte/pull/4980) | Remove Updated field from schemas |
+| 0.1.15 | 2021-07-21 | [4878](https://github.com/airbytehq/airbyte/pull/4878) | Fix incorrect percent\_off and discounts data filed types |
+| 0.1.14 | 2021-07-09 | [4669](https://github.com/airbytehq/airbyte/pull/4669) | Subscriptions Stream now returns all kinds of subscriptions \(including expired and canceled\) |
+| 0.1.13 | 2021-07-03 | [4528](https://github.com/airbytehq/airbyte/pull/4528) | Remove regex for acc validation |
+| 0.1.12 | 2021-06-08 | [3973](https://github.com/airbytehq/airbyte/pull/3973) | Add `AIRBYTE_ENTRYPOINT` for Kubernetes support |
+| 0.1.11 | 2021-05-30 | [3744](https://github.com/airbytehq/airbyte/pull/3744) | Fix types in schema |
+| 0.1.10 | 2021-05-28 | [3728](https://github.com/airbytehq/airbyte/pull/3728) | Update data types to be number instead of int |
+| 0.1.9 | 2021-05-13 | [3367](https://github.com/airbytehq/airbyte/pull/3367) | Add acceptance tests for connected accounts |
+| 0.1.8 | 2021-05-11 | [3566](https://github.com/airbytehq/airbyte/pull/3368) | Bump CDK connectors |