diff --git a/airbyte-integrations/connectors/source-stripe/.coveragerc b/airbyte-integrations/connectors/source-stripe/.coveragerc new file mode 100644 index 0000000000000..34e59889cbe0f --- /dev/null +++ b/airbyte-integrations/connectors/source-stripe/.coveragerc @@ -0,0 +1,3 @@ +[run] +omit = + source_stripe/run.py diff --git a/airbyte-integrations/connectors/source-stripe/acceptance-test-config.yml b/airbyte-integrations/connectors/source-stripe/acceptance-test-config.yml index 8fccd1f0d3270..d4cdddec7cf89 100644 --- a/airbyte-integrations/connectors/source-stripe/acceptance-test-config.yml +++ b/airbyte-integrations/connectors/source-stripe/acceptance-test-config.yml @@ -64,7 +64,7 @@ acceptance_tests: - config_path: "secrets/config.json" timeout_seconds: 3600 future_state: - future_state_path: "integration_tests/abnormal_state.json" + bypass_reason: "This test does not make sense using Concurrent CDK" # The stream `setup_attempts` fails on the `test_read_sequential_slices` step, # `Read 1 of 1 should produce at least one record.`, expecting some records to be set on the stream. skip_comprehensive_incremental_tests: true diff --git a/airbyte-integrations/connectors/source-stripe/erd/discovered_catalog.json b/airbyte-integrations/connectors/source-stripe/erd/discovered_catalog.json index 230c8b9161cfb..89419a72bc71d 100644 --- a/airbyte-integrations/connectors/source-stripe/erd/discovered_catalog.json +++ b/airbyte-integrations/connectors/source-stripe/erd/discovered_catalog.json @@ -208,7 +208,9 @@ }, "default_for": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "interval_description": { "description": "Description of payment interval.", @@ -291,12 +293,24 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, "name": { @@ -311,7 +325,9 @@ "properties": { "allowed_countries": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, @@ -502,7 +518,9 @@ "options": { "description": "Dropdown options.", "type": ["null", "array"], - "items": { "type": ["null", "object"] } + "items": { + "type": ["null", "object"] + } }, "value": { "description": "Selected value.", @@ -633,7 +651,9 @@ "properties": { "account_tax_ids": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "custom_fields": { "description": "Custom fields for the invoice.", @@ -733,21 +753,51 @@ "rate": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "active": { "type": ["null", "boolean"] }, - "country": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "description": { "type": ["null", "string"] }, - "display_name": { "type": ["null", "string"] }, - "effective_percentage": { "type": ["null", "number"] }, - "inclusive": { "type": ["null", "boolean"] }, - "jurisdiction": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"] }, - "percentage": { "type": ["null", "number"] }, - "state": { "type": ["null", "string"] }, - "tax_type": { "type": ["null", "string"] } + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "active": { + "type": ["null", "boolean"] + }, + "country": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "description": { + "type": ["null", "string"] + }, + "display_name": { + "type": ["null", "string"] + }, + "effective_percentage": { + "type": ["null", "number"] + }, + "inclusive": { + "type": ["null", "boolean"] + }, + "jurisdiction": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"] + }, + "percentage": { + "type": ["null", "number"] + }, + "state": { + "type": ["null", "string"] + }, + "tax_type": { + "type": ["null", "string"] + } } }, "taxability_reason": { @@ -770,12 +820,24 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, "name": { @@ -808,8 +870,12 @@ "payment_method_configuration_details": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "parent": { "type": ["null", "string"] } + "id": { + "type": ["null", "string"] + }, + "parent": { + "type": ["null", "string"] + } } }, "client_secret": { @@ -932,12 +998,18 @@ "request": { "description": "The API request information associated with the event.", "oneOf": [ - { "type": ["null", "string"] }, + { + "type": ["null", "string"] + }, { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "idempotency_key": { "type": ["null", "string"] } + "id": { + "type": ["null", "string"] + }, + "idempotency_key": { + "type": ["null", "string"] + } } } ] @@ -1302,12 +1374,16 @@ "alternative_fields_due": { "description": "Fields due for alternative verification", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "original_fields_due": { "description": "Original fields due for verification", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } } @@ -1492,12 +1568,16 @@ "alternative_fields_due": { "description": "Fields due for alternative verification", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "original_fields_due": { "description": "Original fields due for verification", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } } @@ -1929,108 +2009,218 @@ "payment_intent": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "amount": { "type": ["null", "integer"] }, - "amount_capturable": { "type": ["null", "integer"] }, - "amount_received": { "type": ["null", "integer"] }, - "application": { "type": ["null", "string"] }, - "application_fee_amount": { "type": ["null", "integer"] }, - "canceled_at": { "type": ["null", "integer"] }, - "cancellation_reason": { "type": ["null", "string"] }, - "capture_method": { "type": ["null", "string"] }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "integer"] + }, + "amount_capturable": { + "type": ["null", "integer"] + }, + "amount_received": { + "type": ["null", "integer"] + }, + "application": { + "type": ["null", "string"] + }, + "application_fee_amount": { + "type": ["null", "integer"] + }, + "canceled_at": { + "type": ["null", "integer"] + }, + "cancellation_reason": { + "type": ["null", "string"] + }, + "capture_method": { + "type": ["null", "string"] + }, "charges": { "type": ["null", "object"], "properties": { - "object": { "type": ["null", "string"] }, - "data": { "type": ["null", "array"] }, - "has_more": { "type": ["null", "boolean"] }, - "total_count": { "type": ["null", "integer"] }, - "url": { "type": ["null", "string"] } - } - }, - "client_secret": { "type": ["null", "string"] }, - "confirmation_method": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "updated": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "customer": { "type": ["null", "string"] }, - "description": { "type": ["null", "string"] }, - "invoice": { "type": ["null", "string"] }, + "object": { + "type": ["null", "string"] + }, + "data": { + "type": ["null", "array"] + }, + "has_more": { + "type": ["null", "boolean"] + }, + "total_count": { + "type": ["null", "integer"] + }, + "url": { + "type": ["null", "string"] + } + } + }, + "client_secret": { + "type": ["null", "string"] + }, + "confirmation_method": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "updated": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "customer": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "invoice": { + "type": ["null", "string"] + }, "last_payment_error": { "type": ["null", "object"], "properties": { - "charge": { "type": ["null", "string"] }, - "code": { "type": ["null", "string"] }, - "decline_code": { "type": ["null", "string"] }, - "doc_url": { "type": ["null", "string"] }, - "message": { "type": ["null", "string"] }, - "param": { "type": ["null", "string"] }, + "charge": { + "type": ["null", "string"] + }, + "code": { + "type": ["null", "string"] + }, + "decline_code": { + "type": ["null", "string"] + }, + "doc_url": { + "type": ["null", "string"] + }, + "message": { + "type": ["null", "string"] + }, + "param": { + "type": ["null", "string"] + }, "payment_method": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, "acss_debit": { "type": ["null", "object"], "properties": { - "bank_name": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, + "bank_name": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, "institution_number": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "transit_number": { "type": ["null", "string"] } + "last4": { + "type": ["null", "string"] + }, + "transit_number": { + "type": ["null", "string"] + } } }, - "afterpay_clearpay": { "type": ["null", "string"] }, - "alipay": { "type": ["null", "string"] }, + "afterpay_clearpay": { + "type": ["null", "string"] + }, + "alipay": { + "type": ["null", "string"] + }, "au_becs_debit": { "type": ["null", "object"], "properties": { - "bsb_number": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] } + "bsb_number": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + } } }, "bacs_debit": { "type": ["null", "object"], "properties": { - "fingerprint": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "sort_code": { "type": ["null", "string"] } + "fingerprint": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + }, + "sort_code": { + "type": ["null", "string"] + } } }, - "bancontact": { "type": ["null", "string"] }, + "bancontact": { + "type": ["null", "string"] + }, "billing_details": { "type": ["null", "object"], "properties": { "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "email": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "phone": { "type": ["null", "string"] } + "email": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "phone": { + "type": ["null", "string"] + } } }, "boleto": { "type": ["null", "object"], "properties": { - "tax_id": { "type": ["null", "string"] } + "tax_id": { + "type": ["null", "string"] + } } }, "card": { "type": ["null", "object"], "properties": { - "brand": { "type": ["null", "string"] }, + "brand": { + "type": ["null", "string"] + }, "checks": { "type": ["null", "object"], "properties": { @@ -2040,18 +2230,32 @@ "address_postal_code_check": { "type": ["null", "string"] }, - "cvc_check": { "type": ["null", "string"] } + "cvc_check": { + "type": ["null", "string"] + } } }, - "country": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "exp_year": { "type": ["null", "integer"] }, - "fingerprint": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, + "country": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, "generated_from": { "type": ["null", "object"], "properties": { - "charge": { "type": ["null", "string"] }, + "charge": { + "type": ["null", "string"] + }, "payment_method_details": { "type": ["null", "object"], "properties": { @@ -2126,10 +2330,14 @@ } } }, - "type": { "type": ["null", "string"] } + "type": { + "type": ["null", "string"] + } } }, - "type": { "type": ["null", "string"] } + "type": { + "type": ["null", "string"] + } } }, "setup_attempt": { @@ -2137,21 +2345,29 @@ } } }, - "last4": { "type": ["null", "string"] }, + "last4": { + "type": ["null", "string"] + }, "networks": { "type": ["null", "object"], "properties": { "available": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, - "preferred": { "type": ["null", "string"] } + "preferred": { + "type": ["null", "string"] + } } }, "three_d_secure_usage": { "type": ["null", "object"], "properties": { - "supported": { "type": ["null", "boolean"] } + "supported": { + "type": ["null", "boolean"] + } } }, "wallet": { @@ -2160,11 +2376,15 @@ "amex_express_checkout": { "type": ["null", "string"] }, - "apple_pay": { "type": ["null", "string"] }, + "apple_pay": { + "type": ["null", "string"] + }, "dynamic_last4": { "type": ["null", "string"] }, - "google_pay": { "type": ["null", "string"] }, + "google_pay": { + "type": ["null", "string"] + }, "masterpass": { "type": ["null", "object"], "properties": { @@ -2191,8 +2411,12 @@ } } }, - "email": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, + "email": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, "shipping_address": { "type": ["null", "object"], "properties": { @@ -2218,8 +2442,12 @@ } } }, - "samsung_pay": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] }, + "samsung_pay": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, "visa_checkout": { "type": ["null", "object"], "properties": { @@ -2246,8 +2474,12 @@ } } }, - "email": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, + "email": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, "shipping_address": { "type": ["null", "object"], "properties": { @@ -2281,18 +2513,26 @@ "type": ["null", "object"], "properties": {} }, - "created": { "type": ["null", "integer"] }, - "customer": { "type": ["null", "string"] }, + "created": { + "type": ["null", "integer"] + }, + "customer": { + "type": ["null", "string"] + }, "eps": { "type": ["null", "object"], "properties": { - "bank": { "type": ["null", "string"] } + "bank": { + "type": ["null", "string"] + } } }, "fpx": { "type": ["null", "object"], "properties": { - "bank": { "type": ["null", "string"] } + "bank": { + "type": ["null", "string"] + } } }, "giropay": { @@ -2306,14 +2546,18 @@ "ideal": { "type": ["null", "object"], "properties": { - "bank": { "type": ["null", "string"] } + "bank": { + "type": ["null", "string"] + } } }, "interac_present": { "type": ["null", "object"], "properties": {} }, - "livemode": { "type": ["null", "boolean"] }, + "livemode": { + "type": ["null", "boolean"] + }, "metadata": { "type": ["null", "object"], "properties": {} @@ -2325,84 +2569,139 @@ "p24": { "type": ["null", "object"], "properties": { - "bank": { "type": ["null", "string"] } + "bank": { + "type": ["null", "string"] + } } }, "sepa_debit": { "type": ["null", "object"], "properties": { - "bank_code": { "type": ["null", "string"] }, - "branch_code": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, + "bank_code": { + "type": ["null", "string"] + }, + "branch_code": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, "generated_from": { "type": ["null", "object"], "properties": { - "charge": { "type": ["null", "string"] }, + "charge": { + "type": ["null", "string"] + }, "setup_attempt": { "type": ["null", "string"] } } }, - "last4": { "type": ["null", "string"] } + "last4": { + "type": ["null", "string"] + } } }, "sofort": { "type": ["null", "object"], "properties": { - "country": { "type": ["null", "string"] } + "country": { + "type": ["null", "string"] + } } }, - "type": { "type": ["null", "string"] }, + "type": { + "type": ["null", "string"] + }, "wechat_pay": { "type": ["null", "object"], "properties": {} } } }, - "payment_method_type": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } + "payment_method_type": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } } }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"], "properties": {} }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"], + "properties": {} + }, "next_action": { "type": ["null", "object"], "properties": { "alipay_handle_redirect": { "type": ["null", "object"], "properties": { - "native_data": { "type": ["null", "string"] }, - "native_url": { "type": ["null", "string"] }, - "return_url": { "type": ["null", "string"] }, - "url": { "type": ["null", "string"] } + "native_data": { + "type": ["null", "string"] + }, + "native_url": { + "type": ["null", "string"] + }, + "return_url": { + "type": ["null", "string"] + }, + "url": { + "type": ["null", "string"] + } } }, "boleto_display_details": { "type": ["null", "object"], "properties": { - "expires_at": { "type": ["null", "integer"] }, - "hosted_voucher_url": { "type": ["null", "string"] }, - "number": { "type": ["null", "string"] }, - "pdf": { "type": ["null", "string"] } + "expires_at": { + "type": ["null", "integer"] + }, + "hosted_voucher_url": { + "type": ["null", "string"] + }, + "number": { + "type": ["null", "string"] + }, + "pdf": { + "type": ["null", "string"] + } } }, "oxxo_display_details": { "type": ["null", "object"], "properties": { - "expires_after": { "type": ["null", "integer"] }, - "hosted_voucher_url": { "type": ["null", "string"] }, - "number": { "type": ["null", "string"] } + "expires_after": { + "type": ["null", "integer"] + }, + "hosted_voucher_url": { + "type": ["null", "string"] + }, + "number": { + "type": ["null", "string"] + } } }, "redirect_to_url": { "type": ["null", "object"], "properties": { - "return_url": { "type": ["null", "string"] }, - "url": { "type": ["null", "string"] } + "return_url": { + "type": ["null", "string"] + }, + "url": { + "type": ["null", "string"] + } } }, - "type": { "type": ["null", "string"] }, + "type": { + "type": ["null", "string"] + }, "use_stripe_sdk": { "type": ["null", "object"], "properties": {} @@ -2410,7 +2709,9 @@ "verify_with_microdeposits": { "type": ["null", "object"], "properties": { - "arrival_date": { "type": ["null", "integer"] }, + "arrival_date": { + "type": ["null", "integer"] + }, "hosted_verification_url": { "type": ["null", "string"] } @@ -2419,84 +2720,156 @@ "wechat_pay_display_qr_code": { "type": ["null", "object"], "properties": { - "data": { "type": ["null", "string"] }, - "image_data_url": { "type": ["null", "string"] } + "data": { + "type": ["null", "string"] + }, + "image_data_url": { + "type": ["null", "string"] + } } }, "wechat_pay_redirect_to_android_app": { "type": ["null", "object"], "properties": { - "app_id": { "type": ["null", "string"] }, - "nonce_str": { "type": ["null", "string"] }, - "package": { "type": ["null", "string"] }, - "partner_id": { "type": ["null", "string"] }, - "prepay_id": { "type": ["null", "string"] }, - "sign": { "type": ["null", "string"] }, - "timestamp": { "type": ["null", "string"] } + "app_id": { + "type": ["null", "string"] + }, + "nonce_str": { + "type": ["null", "string"] + }, + "package": { + "type": ["null", "string"] + }, + "partner_id": { + "type": ["null", "string"] + }, + "prepay_id": { + "type": ["null", "string"] + }, + "sign": { + "type": ["null", "string"] + }, + "timestamp": { + "type": ["null", "string"] + } } }, "wechat_pay_redirect_to_ios_app": { "type": ["null", "object"], "properties": { - "native_url": { "type": ["null", "string"] } + "native_url": { + "type": ["null", "string"] + } } } } }, - "on_behalf_of": { "type": ["null", "string"] }, - "payment_method": { "type": ["null", "string"] }, + "on_behalf_of": { + "type": ["null", "string"] + }, + "payment_method": { + "type": ["null", "string"] + }, "payment_method_options": { "type": ["null", "object"], "properties": {} }, "payment_method_types": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } + }, + "receipt_email": { + "type": ["null", "string"] + }, + "review": { + "type": ["null", "string"] + }, + "setup_future_usage": { + "type": ["null", "string"] }, - "receipt_email": { "type": ["null", "string"] }, - "review": { "type": ["null", "string"] }, - "setup_future_usage": { "type": ["null", "string"] }, "shipping": { "type": ["null", "object"], "properties": { "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "carrier": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "phone": { "type": ["null", "string"] }, - "tracking_number": { "type": ["null", "string"] } + "carrier": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "phone": { + "type": ["null", "string"] + }, + "tracking_number": { + "type": ["null", "string"] + } } }, - "source": { "type": ["null", "string"] }, - "statement_description": { "type": ["null", "string"] }, - "statement_descriptor_suffix": { "type": ["null", "string"] }, - "status": { "type": ["null", "string"] }, + "source": { + "type": ["null", "string"] + }, + "statement_description": { + "type": ["null", "string"] + }, + "statement_descriptor_suffix": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, "transfer_data": { "type": ["null", "object"], "properties": { - "amount": { "type": ["null", "integer"] }, - "destination": { "type": ["null", "string"] } + "amount": { + "type": ["null", "integer"] + }, + "destination": { + "type": ["null", "string"] + } } }, - "transfer_group": { "type": ["null", "string"] }, - "latest_charge": { "type": ["null", "string"] }, - "statement_descriptor": { "type": ["null", "string"] }, + "transfer_group": { + "type": ["null", "string"] + }, + "latest_charge": { + "type": ["null", "string"] + }, + "statement_descriptor": { + "type": ["null", "string"] + }, "amount_details": { "type": ["null", "object"], "properties": { "tip": { "type": ["null", "object"], "properties": { - "amount": { "type": ["null", "integer"] } + "amount": { + "type": ["null", "integer"] + } } } } @@ -2504,7 +2877,9 @@ "processing": { "type": ["null", "object"], "properties": { - "type": { "type": ["null", "string"] }, + "type": { + "type": ["null", "string"] + }, "card": { "type": ["null", "object"], "properties": { @@ -2514,7 +2889,9 @@ "approval_requested": { "type": ["null", "boolean"] }, - "completes_at": { "type": ["null", "integer"] } + "completes_at": { + "type": ["null", "integer"] + } } } } @@ -2524,15 +2901,23 @@ "automatic_payment_methods": { "type": ["null", "object"], "properties": { - "allow_redirects": { "type": ["null", "string"] }, - "enabled": { "type": ["null", "boolean"] } + "allow_redirects": { + "type": ["null", "string"] + }, + "enabled": { + "type": ["null", "boolean"] + } } }, "payment_method_configuration_details": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "parent": { "type": ["null", "string"] } + "id": { + "type": ["null", "string"] + }, + "parent": { + "type": ["null", "string"] + } } } } @@ -2602,12 +2987,24 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, "email": { @@ -2885,53 +3282,104 @@ "setup_intent": { "type": ["null", "object"], "properties": { - "id": { "type": ["string"] }, - "object": { "type": ["string"], "enum": ["setup_intent"] }, - "application": { "type": ["null", "string"] }, - "cancellation_reason": { "type": ["null", "string"] }, - "created": { "type": ["integer"] }, - "updated": { "type": ["null", "integer"] }, - "customer": { "type": ["null", "string"] }, - "description": { "type": ["null", "string"] }, + "id": { + "type": ["string"] + }, + "object": { + "type": ["string"], + "enum": ["setup_intent"] + }, + "application": { + "type": ["null", "string"] + }, + "cancellation_reason": { + "type": ["null", "string"] + }, + "created": { + "type": ["integer"] + }, + "updated": { + "type": ["null", "integer"] + }, + "customer": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, "flow_directions": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } - }, - "last_setup_error": { "type": ["null", "string"] }, - "latest_attempt": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "mandate": { "type": ["null", "string"] }, - "metadata": { "type": ["null", "object"] }, - "next_action": { "type": ["null", "string"] }, - "on_behalf_of": { "type": ["null", "string"] }, - "payment_method": { "type": ["null", "string"] }, + "items": { + "type": ["null", "string"] + } + }, + "last_setup_error": { + "type": ["null", "string"] + }, + "latest_attempt": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "mandate": { + "type": ["null", "string"] + }, + "metadata": { + "type": ["null", "object"] + }, + "next_action": { + "type": ["null", "string"] + }, + "on_behalf_of": { + "type": ["null", "string"] + }, + "payment_method": { + "type": ["null", "string"] + }, "payment_method_options": { "type": ["null", "object"], "additionalProperties": true }, "payment_method_types": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } + }, + "single_use_mandate": { + "type": ["null", "string"] + }, + "status": { + "type": ["string"] }, - "single_use_mandate": { "type": ["null", "string"] }, - "status": { "type": ["string"] }, "usage": { "type": ["string"], "enum": ["on_session", "off_session"] }, - "client_secret": { "type": ["null", "string"] }, + "client_secret": { + "type": ["null", "string"] + }, "automatic_payment_methods": { "type": ["null", "object"], "properties": { - "allow_redirects": { "type": ["null", "string"] }, - "enabled": { "type": ["null", "boolean"] } + "allow_redirects": { + "type": ["null", "string"] + }, + "enabled": { + "type": ["null", "boolean"] + } } }, "payment_method_configuration_details": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "parent": { "type": ["null", "string"] } + "id": { + "type": ["null", "string"] + }, + "parent": { + "type": ["null", "string"] + } } } } @@ -3024,22 +3472,34 @@ "support_address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } - } - }, - "support_email": { - "description": "Support email for the business.", - "type": ["null", "string"] - }, - "support_phone": { - "description": "Support phone number for the business.", - "type": ["null", "string"] - }, + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } + } + }, + "support_email": { + "description": "Support email for the business.", + "type": ["null", "string"] + }, + "support_phone": { + "description": "Support phone number for the business.", + "type": ["null", "string"] + }, "support_url": { "description": "Support URL for the business.", "type": ["null", "string"] @@ -3157,12 +3617,24 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, "address_kana": { @@ -3170,13 +3642,27 @@ "type": ["null", "object"], "additionalProperties": true, "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] }, - "town": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + }, + "town": { + "type": ["null", "string"] + } } }, "address_kanji": { @@ -3184,13 +3670,27 @@ "type": ["null", "object"], "additionalProperties": true, "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] }, - "town": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + }, + "town": { + "type": ["null", "string"] + } } }, "directors_provided": { @@ -3274,9 +3774,15 @@ "type": ["null", "object"], "additionalProperties": true, "properties": { - "back": { "type": ["null", "string"] }, - "details": { "type": ["null", "string"] }, - "details_code": { "type": ["null", "string"] } + "back": { + "type": ["null", "string"] + }, + "details": { + "type": ["null", "string"] + }, + "details_code": { + "type": ["null", "string"] + } } } } @@ -3312,10 +3818,19 @@ "type": ["null", "object"], "additionalProperties": true, "properties": { - "data": { "type": ["null", "array"] }, - "has_more": { "type": ["null", "boolean"] }, - "object": { "enum": ["list"], "type": ["null", "string"] }, - "url": { "type": ["null", "string"] } + "data": { + "type": ["null", "array"] + }, + "has_more": { + "type": ["null", "boolean"] + }, + "object": { + "enum": ["list"], + "type": ["null", "string"] + }, + "url": { + "type": ["null", "string"] + } } }, "id": { @@ -3343,12 +3858,24 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, "address_kana": { @@ -3356,13 +3883,27 @@ "type": ["null", "object"], "additionalProperties": true, "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] }, - "town": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + }, + "town": { + "type": ["null", "string"] + } } }, "address_kanji": { @@ -3370,13 +3911,27 @@ "type": ["null", "object"], "additionalProperties": true, "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] }, - "town": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + }, + "town": { + "type": ["null", "string"] + } } }, "created": { @@ -3388,9 +3943,15 @@ "type": ["null", "object"], "additionalProperties": true, "properties": { - "day": { "type": ["null", "number"] }, - "month": { "type": ["null", "number"] }, - "year": { "type": ["null", "number"] } + "day": { + "type": ["null", "number"] + }, + "month": { + "type": ["null", "number"] + }, + "year": { + "type": ["null", "number"] + } } }, "email": { @@ -3412,7 +3973,9 @@ "full_name_aliases": { "description": "Aliases of the full name of the individual.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "full_requirements": { "description": "Full requirements status and details for the individual.", @@ -3427,12 +3990,16 @@ "alternative_fields_due": { "description": "Fields alternative to those currently due.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "original_fields_due": { "description": "Original fields initially due.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, @@ -3447,26 +4014,38 @@ "type": ["null", "object"], "additionalProperties": true, "properties": { - "code": { "type": ["null", "string"] }, - "reason": { "type": ["null", "string"] }, - "requirement": { "type": ["null", "string"] } + "code": { + "type": ["null", "string"] + }, + "reason": { + "type": ["null", "string"] + }, + "requirement": { + "type": ["null", "string"] + } } } }, "eventually_due": { "description": "Fields eventually due for full requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "past_due": { "description": "Fields past due for full requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "pending_verification": { "description": "Fields pending verification for full requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, @@ -3518,12 +4097,24 @@ "registered_address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, "relationship": { @@ -3570,19 +4161,25 @@ "alternative_fields_due": { "description": "Fields alternative to those currently due.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "original_fields_due": { "description": "Original fields initially due.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, "currently_due": { "description": "Fields currently due for individual requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "errors": { "description": "Errors related to individual requirements.", @@ -3591,26 +4188,38 @@ "type": ["null", "object"], "additionalProperties": true, "properties": { - "code": { "type": ["null", "string"] }, - "reason": { "type": ["null", "string"] }, - "requirement": { "type": ["null", "string"] } + "code": { + "type": ["null", "string"] + }, + "reason": { + "type": ["null", "string"] + }, + "requirement": { + "type": ["null", "string"] + } } } }, "eventually_due": { "description": "Fields eventually due for individual requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "past_due": { "description": "Fields past due for individual requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "pending_verification": { "description": "Fields pending verification for individual requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, @@ -3628,22 +4237,40 @@ "type": ["null", "object"], "additionalProperties": true, "properties": { - "back": { "type": ["null", "string"] }, - "details": { "type": ["null", "string"] }, - "details_code": { "type": ["null", "string"] } + "back": { + "type": ["null", "string"] + }, + "details": { + "type": ["null", "string"] + }, + "details_code": { + "type": ["null", "string"] + } } }, - "details": { "type": ["null", "string"] }, - "details_code": { "type": ["null", "string"] }, + "details": { + "type": ["null", "string"] + }, + "details_code": { + "type": ["null", "string"] + }, "document": { "description": "Base document verification details.", "type": ["null", "object"], "additionalProperties": true, "properties": { - "back": { "type": ["null", "string"] }, - "details": { "type": ["null", "string"] }, - "details_code": { "type": ["null", "string"] }, - "front": { "type": ["null", "string"] } + "back": { + "type": ["null", "string"] + }, + "details": { + "type": ["null", "string"] + }, + "details_code": { + "type": ["null", "string"] + }, + "front": { + "type": ["null", "string"] + } } }, "status": { @@ -3682,12 +4309,16 @@ "alternative_fields_due": { "description": "Fields alternative to those currently due.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "original_fields_due": { "description": "Original fields initially due.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } } @@ -3695,7 +4326,9 @@ "currently_due": { "description": "Fields currently due for entity requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "disabled_reason": { "description": "Reason for entity requirements being disabled.", @@ -3708,26 +4341,38 @@ "type": ["null", "object"], "additionalProperties": true, "properties": { - "code": { "type": ["null", "string"] }, - "reason": { "type": ["null", "string"] }, - "requirement": { "type": ["null", "string"] } + "code": { + "type": ["null", "string"] + }, + "reason": { + "type": ["null", "string"] + }, + "requirement": { + "type": ["null", "string"] + } } } }, "eventually_due": { "description": "Fields eventually due for entity requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "past_due": { "description": "Fields past due for entity requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "pending_verification": { "description": "Fields pending verification for entity requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, @@ -3777,12 +4422,16 @@ "alternative_fields_due": { "description": "Fields alternative to those currently due.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "original_fields_due": { "description": "Original fields initially due.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } } @@ -3794,7 +4443,9 @@ "currently_due": { "description": "Fields currently due for future requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "disabled_reason": { "description": "Reason for future requirements being disabled.", @@ -3806,26 +4457,38 @@ "items": { "type": ["null", "object"], "properties": { - "code": { "type": ["null", "string"] }, - "reason": { "type": ["null", "string"] }, - "requirement": { "type": ["null", "string"] } + "code": { + "type": ["null", "string"] + }, + "reason": { + "type": ["null", "string"] + }, + "requirement": { + "type": ["null", "string"] + } } } }, "eventually_due": { "description": "Fields eventually due for future requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "past_due": { "description": "Fields past due for future requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "pending_verification": { "description": "Fields pending verification for future requirements.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, @@ -3876,8 +4539,32 @@ }, "delivery_estimate": { "description": "Estimated delivery time for the shipping rate", - "type": ["null", "string"] - }, + "type": ["null", "object"], + "properties": { + "maximum": { + "type": ["null", "object"], + "properties": { + "unit": { + "type": ["null", "string"] + }, + "value": { + "type": ["null", "integer"] + } + } + }, + "minimum": { + "type": ["null", "object"], + "properties": { + "unit": { + "type": ["null", "string"] + }, + "value": { + "type": ["null", "integer"] + } + } + } + } + }, "display_name": { "description": "Name displayed for the shipping rate", "type": ["null", "string"] @@ -3938,34 +4625,75 @@ "json_schema": { "type": ["null", "object"], "properties": { - "fee": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "source": { "type": ["null", "string"] }, + "fee": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "source": { + "type": ["null", "string"] + }, "fee_details": { "type": ["null", "array"], "items": { "properties": { - "application": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] }, - "description": { "type": ["null", "string"] }, - "amount": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] } + "application": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } }, "type": ["null", "object"] } }, - "available_on": { "type": ["null", "integer"] }, - "status": { "type": ["null", "string"] }, - "description": { "type": ["null", "string"] }, - "net": { "type": ["null", "integer"] }, - "exchange_rate": { "type": ["null", "number"] }, - "type": { "type": ["null", "string"] }, - "sourced_transfers": { "items": {}, "type": ["null", "array"] }, - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "amount": { "type": ["null", "integer"] }, - "reporting_category": { "type": ["null", "string"] } + "available_on": { + "type": ["null", "integer"] + }, + "status": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "net": { + "type": ["null", "integer"] + }, + "exchange_rate": { + "type": ["null", "number"] + }, + "type": { + "type": ["null", "string"] + }, + "sourced_transfers": { + "items": {}, + "type": ["null", "array"] + }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "amount": { + "type": ["null", "integer"] + }, + "reporting_category": { + "type": ["null", "string"] + } } }, "supported_sync_modes": ["full_refresh", "incremental"], @@ -3978,35 +4706,77 @@ "json_schema": { "type": ["null", "object"], "properties": { - "fee": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "source": { "type": ["null", "string"] }, + "fee": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "source": { + "type": ["null", "string"] + }, "fee_details": { "type": ["null", "array"], "items": { "properties": { - "application": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] }, - "description": { "type": ["null", "string"] }, - "amount": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] } + "application": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } }, "type": ["null", "object"] } }, - "available_on": { "type": ["null", "integer"] }, - "status": { "type": ["null", "string"] }, - "description": { "type": ["null", "string"] }, - "net": { "type": ["null", "integer"] }, - "exchange_rate": { "type": ["null", "number"] }, - "type": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "updated": { "type": ["null", "integer"] }, - "amount": { "type": ["null", "integer"] }, - "reporting_category": { "type": ["null", "string"] }, - "payout": { "type": ["null", "string"] } + "available_on": { + "type": ["null", "integer"] + }, + "status": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "net": { + "type": ["null", "integer"] + }, + "exchange_rate": { + "type": ["null", "number"] + }, + "type": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "updated": { + "type": ["null", "integer"] + }, + "amount": { + "type": ["null", "integer"] + }, + "reporting_category": { + "type": ["null", "string"] + }, + "payout": { + "type": ["null", "string"] + } } }, "supported_sync_modes": ["full_refresh", "incremental"], @@ -4306,18 +5076,30 @@ "additionalProperties": true, "type": ["null", "object"], "properties": { - "bsb_number": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] } + "bsb_number": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + } } }, "bacs_debit": { "additionalProperties": true, "type": ["null", "object"], "properties": { - "fingerprint": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "sort_code": { "type": ["null", "string"] } + "fingerprint": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + }, + "sort_code": { + "type": ["null", "string"] + } } }, "bancontact": { @@ -4331,58 +5113,104 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "email": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "phone": { "type": ["null", "string"] } + "email": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "phone": { + "type": ["null", "string"] + } } }, "card": { "additionalProperties": true, "type": ["null", "object"], "properties": { - "brand": { "type": ["null", "string"] }, + "brand": { + "type": ["null", "string"] + }, "checks": { "additionalProperties": true, "type": ["null", "object"], "properties": { - "address_line1_check": { "type": ["null", "string"] }, - "address_postal_code_check": { "type": ["null", "string"] }, - "cvc_check": { "type": ["null", "string"] } + "address_line1_check": { + "type": ["null", "string"] + }, + "address_postal_code_check": { + "type": ["null", "string"] + }, + "cvc_check": { + "type": ["null", "string"] + } } }, - "country": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "exp_year": { "type": ["null", "integer"] }, - "fingerprint": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, + "country": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, "generated_from": { "additionalProperties": true, "type": ["null", "object"] }, - "last4": { "type": ["null", "string"] }, + "last4": { + "type": ["null", "string"] + }, "networks": { "additionalProperties": true, "type": ["null", "object"], "properties": { "available": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, - "preferred": { "type": ["null", "string"] } + "preferred": { + "type": ["null", "string"] + } } }, "three_d_secure_usage": { "additionalProperties": true, "type": ["null", "object"], - "properties": { "supported": { "type": ["null", "boolean"] } } + "properties": { + "supported": { + "type": ["null", "boolean"] + } + } }, "wallet": { "additionalProperties": true, @@ -4394,41 +5222,78 @@ "additionalProperties": true, "type": ["null", "object"] }, - "created": { "type": ["null", "integer"] }, - "updated": { "type": ["null", "integer"] }, + "created": { + "type": ["null", "integer"] + }, + "updated": { + "type": ["null", "integer"] + }, "customer": { "type": ["null", "object"], "properties": { - "metadata": { "type": ["null", "object"], "properties": {} }, + "metadata": { + "type": ["null", "object"], + "properties": {} + }, "preferred_locales": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "invoice_settings": { "type": ["null", "object"], "properties": { "custom_fields": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, - "default_payment_method": { "type": ["null", "string"] }, - "footer": { "type": ["null", "string"] } + "default_payment_method": { + "type": ["null", "string"] + }, + "footer": { + "type": ["null", "string"] + } } }, - "name": { "type": ["null", "string"] }, - "tax_exempt": { "type": ["null", "string"] }, - "next_invoice_sequence": { "type": ["null", "integer"] }, - "balance": { "type": ["null", "integer"] }, - "phone": { "type": ["null", "string"] }, + "name": { + "type": ["null", "string"] + }, + "tax_exempt": { + "type": ["null", "string"] + }, + "next_invoice_sequence": { + "type": ["null", "integer"] + }, + "balance": { + "type": ["null", "integer"] + }, + "phone": { + "type": ["null", "string"] + }, "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, "shipping": { @@ -4437,125 +5302,263 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } - } - }, - "name": { "type": ["null", "string"] }, - "phone": { "type": ["null", "string"] } - } - }, - "sources": { - "anyOf": [ - { - "type": ["null", "array"], - "items": { - "type": ["null", "object"], + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } + } + }, + "name": { + "type": ["null", "string"] + }, + "phone": { + "type": ["null", "string"] + } + } + }, + "sources": { + "anyOf": [ + { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], "properties": { "metadata": { "type": ["null", "object"], "properties": {} }, - "type": { "type": ["null", "string"] }, - "address_zip": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, + "type": { + "type": ["null", "string"] + }, + "address_zip": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, "card": { "type": ["null", "object"], "properties": { - "fingerprint": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "dynamic_last4": { "type": ["null", "string"] }, + "fingerprint": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + }, + "dynamic_last4": { + "type": ["null", "string"] + }, "address_line1_check": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, + "exp_month": { + "type": ["null", "integer"] + }, "tokenization_method": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "exp_year": { "type": ["null", "integer"] }, - "three_d_secure": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, - "brand": { "type": ["null", "string"] }, - "cvc_check": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "address_zip_check": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } + "name": { + "type": ["null", "string"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "three_d_secure": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, + "brand": { + "type": ["null", "string"] + }, + "cvc_check": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "address_zip_check": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } } }, - "statement_descriptor": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, - "address_country": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, - "dynamic_last4": { "type": ["null", "string"] }, - "exp_year": { "type": ["null", "integer"] }, - "last4": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "brand": { "type": ["null", "string"] }, - "address_line2": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "amount": { "type": ["null", "integer"] }, - "cvc_check": { "type": ["null", "string"] }, - "usage": { "type": ["null", "string"] }, - "address_line1": { "type": ["null", "string"] }, + "statement_descriptor": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "address_country": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, + "dynamic_last4": { + "type": ["null", "string"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "last4": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "brand": { + "type": ["null", "string"] + }, + "address_line2": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "integer"] + }, + "cvc_check": { + "type": ["null", "string"] + }, + "usage": { + "type": ["null", "string"] + }, + "address_line1": { + "type": ["null", "string"] + }, "owner": { "type": ["null", "object"], "properties": { - "verified_address": { "type": ["null", "string"] }, - "email": { "type": ["null", "string"] }, + "verified_address": { + "type": ["null", "string"] + }, + "email": { + "type": ["null", "string"] + }, "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "verified_email": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "phone": { "type": ["null", "string"] }, - "verified_name": { "type": ["null", "string"] }, - "verified_phone": { "type": ["null", "string"] } + "verified_email": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "phone": { + "type": ["null", "string"] + }, + "verified_name": { + "type": ["null", "string"] + }, + "verified_phone": { + "type": ["null", "string"] + } } }, - "tokenization_method": { "type": ["null", "string"] }, - "client_secret": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "address_city": { "type": ["null", "string"] }, - "currency": { "type": ["null", "string"] }, - "address_line1_check": { "type": ["null", "string"] }, + "tokenization_method": { + "type": ["null", "string"] + }, + "client_secret": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "address_city": { + "type": ["null", "string"] + }, + "currency": { + "type": ["null", "string"] + }, + "address_line1_check": { + "type": ["null", "string"] + }, "receiver": { "type": ["null", "object"], "properties": { "refund_attributes_method": { "type": ["null", "string"] }, - "amount_returned": { "type": ["null", "integer"] }, - "amount_received": { "type": ["null", "integer"] }, + "amount_returned": { + "type": ["null", "integer"] + }, + "amount_received": { + "type": ["null", "integer"] + }, "refund_attributes_status": { "type": ["null", "string"] }, - "address": { "type": ["null", "string"] }, - "amount_charged": { "type": ["null", "integer"] } + "address": { + "type": ["null", "string"] + }, + "amount_charged": { + "type": ["null", "integer"] + } } }, - "flow": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, + "flow": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, "ach_credit_transfer": { "type": ["null", "object"], "properties": { - "bank_name": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "routing_number": { "type": ["null", "string"] }, - "swift_code": { "type": ["null", "string"] }, + "bank_name": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "routing_number": { + "type": ["null", "string"] + }, + "swift_code": { + "type": ["null", "string"] + }, "refund_account_holder_type": { "type": ["null", "string"] }, @@ -4568,14 +5571,26 @@ "refund_routing_number": { "type": ["null", "string"] }, - "account_number": { "type": ["null", "string"] } + "account_number": { + "type": ["null", "string"] + } } }, - "customer": { "type": ["null", "string"] }, - "address_zip_check": { "type": ["null", "string"] }, - "status": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "address_state": { "type": ["null", "string"] }, + "customer": { + "type": ["null", "string"] + }, + "address_zip_check": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "address_state": { + "type": ["null", "string"] + }, "alipay": { "type": ["null", "object"], "properties": {} @@ -4584,7 +5599,10 @@ "type": ["null", "object"], "properties": {} }, - "eps": { "type": ["null", "object"], "properties": {} }, + "eps": { + "type": ["null", "object"], + "properties": {} + }, "ideal": { "type": ["null", "object"], "properties": {} @@ -4596,10 +5614,18 @@ "redirect": { "type": ["null", "object"], "properties": { - "failure_reason": { "type": ["null", "string"] }, - "return_url": { "type": ["null", "string"] }, - "status": { "type": ["null", "string"] }, - "url": { "type": ["null", "string"] } + "failure_reason": { + "type": ["null", "string"] + }, + "return_url": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "url": { + "type": ["null", "string"] + } } } } @@ -4612,200 +5638,422 @@ "type": ["null", "object"], "properties": {} }, - "type": { "type": ["null", "string"] }, - "address_zip": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "card": { - "type": ["null", "object"], - "properties": { - "fingerprint": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "dynamic_last4": { "type": ["null", "string"] }, - "address_line1_check": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "tokenization_method": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "exp_year": { "type": ["null", "integer"] }, - "three_d_secure": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, - "brand": { "type": ["null", "string"] }, - "cvc_check": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "address_zip_check": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } - } + "type": { + "type": ["null", "string"] }, - "statement_descriptor": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, - "address_country": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, - "dynamic_last4": { "type": ["null", "string"] }, - "exp_year": { "type": ["null", "integer"] }, - "last4": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "brand": { "type": ["null", "string"] }, - "address_line2": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "amount": { "type": ["null", "integer"] }, - "cvc_check": { "type": ["null", "string"] }, - "usage": { "type": ["null", "string"] }, - "address_line1": { "type": ["null", "string"] }, - "owner": { - "type": ["null", "object"], - "properties": { - "verified_address": { "type": ["null", "string"] }, - "email": { "type": ["null", "string"] }, - "address": { - "type": ["null", "object"], - "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } - } - }, - "verified_email": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "phone": { "type": ["null", "string"] }, - "verified_name": { "type": ["null", "string"] }, - "verified_phone": { "type": ["null", "string"] } - } + "address_zip": { + "type": ["null", "string"] }, - "tokenization_method": { "type": ["null", "string"] }, - "client_secret": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "address_city": { "type": ["null", "string"] }, - "currency": { "type": ["null", "string"] }, - "address_line1_check": { "type": ["null", "string"] }, - "receiver": { + "livemode": { + "type": ["null", "boolean"] + }, + "card": { "type": ["null", "object"], "properties": { - "refund_attributes_method": { + "fingerprint": { "type": ["null", "string"] }, - "amount_returned": { "type": ["null", "integer"] }, - "amount_received": { "type": ["null", "integer"] }, - "refund_attributes_status": { + "last4": { "type": ["null", "string"] }, - "address": { "type": ["null", "string"] }, - "amount_charged": { "type": ["null", "integer"] } - } - }, - "flow": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "ach_credit_transfer": { - "type": ["null", "object"], - "properties": { - "bank_name": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "routing_number": { "type": ["null", "string"] }, - "swift_code": { "type": ["null", "string"] }, - "refund_account_holder_type": { + "dynamic_last4": { "type": ["null", "string"] }, - "refund_account_holder_name": { + "address_line1_check": { "type": ["null", "string"] }, - "refund_account_number": { + "exp_month": { + "type": ["null", "integer"] + }, + "tokenization_method": { "type": ["null", "string"] }, - "refund_routing_number": { + "name": { + "type": ["null", "string"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "three_d_secure": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, + "brand": { + "type": ["null", "string"] + }, + "cvc_check": { "type": ["null", "string"] }, - "account_number": { "type": ["null", "string"] } + "country": { + "type": ["null", "string"] + }, + "address_zip_check": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } } }, - "customer": { "type": ["null", "string"] }, - "address_zip_check": { "type": ["null", "string"] }, - "status": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "address_state": { "type": ["null", "string"] }, - "alipay": { - "type": ["null", "object"], - "properties": {} + "statement_descriptor": { + "type": ["null", "string"] }, - "bancontact": { - "type": ["null", "object"], - "properties": {} + "id": { + "type": ["null", "string"] }, - "eps": { "type": ["null", "object"], "properties": {} }, - "ideal": { "type": ["null", "object"], "properties": {} }, - "multibanco": { - "type": ["null", "object"], - "properties": {} + "address_country": { + "type": ["null", "string"] }, - "redirect": { - "type": ["null", "object"], - "properties": { - "failure_reason": { "type": ["null", "string"] }, - "return_url": { "type": ["null", "string"] }, - "status": { "type": ["null", "string"] }, - "url": { "type": ["null", "string"] } - } - } - } - } - ] - }, - "delinquent": { "type": ["null", "boolean"] }, - "description": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "default_source": { "type": ["null", "string"] }, - "cards": { - "type": ["null", "array"], - "items": { - "type": ["null", "object"], - "properties": { - "metadata": { - "type": ["null", "object"], - "properties": {} - }, - "object": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "dynamic_last4": { "type": ["null", "string"] }, - "exp_year": { "type": ["null", "integer"] }, - "last4": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, - "brand": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "customer": { "type": ["null", "string"] }, - "cvc_check": { "type": ["null", "string"] }, - "address_line2": { "type": ["null", "string"] }, - "address_line1": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "address_zip": { "type": ["null", "string"] }, - "address_city": { "type": ["null", "string"] }, - "address_country": { "type": ["null", "string"] }, - "address_line1_check": { "type": ["null", "string"] }, - "tokenization_method": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "address_state": { "type": ["null", "string"] }, - "address_zip_check": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } - } - } - }, - "email": { "type": ["null", "string"] }, - "default_card": { "type": ["null", "string"] }, - "subscriptions": { - "type": ["null", "object"], - "properties": { - "object": { "type": ["null", "string"] }, - "data": { "type": ["null", "array"] }, - "has_more": { "type": ["null", "boolean"] }, - "total_count": { "type": ["null", "number"] }, - "url": { "type": ["null", "string"] } + "funding": { + "type": ["null", "string"] + }, + "dynamic_last4": { + "type": ["null", "string"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "last4": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "brand": { + "type": ["null", "string"] + }, + "address_line2": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "integer"] + }, + "cvc_check": { + "type": ["null", "string"] + }, + "usage": { + "type": ["null", "string"] + }, + "address_line1": { + "type": ["null", "string"] + }, + "owner": { + "type": ["null", "object"], + "properties": { + "verified_address": { + "type": ["null", "string"] + }, + "email": { + "type": ["null", "string"] + }, + "address": { + "type": ["null", "object"], + "properties": { + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } + } + }, + "verified_email": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "phone": { + "type": ["null", "string"] + }, + "verified_name": { + "type": ["null", "string"] + }, + "verified_phone": { + "type": ["null", "string"] + } + } + }, + "tokenization_method": { + "type": ["null", "string"] + }, + "client_secret": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "address_city": { + "type": ["null", "string"] + }, + "currency": { + "type": ["null", "string"] + }, + "address_line1_check": { + "type": ["null", "string"] + }, + "receiver": { + "type": ["null", "object"], + "properties": { + "refund_attributes_method": { + "type": ["null", "string"] + }, + "amount_returned": { + "type": ["null", "integer"] + }, + "amount_received": { + "type": ["null", "integer"] + }, + "refund_attributes_status": { + "type": ["null", "string"] + }, + "address": { + "type": ["null", "string"] + }, + "amount_charged": { + "type": ["null", "integer"] + } + } + }, + "flow": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "ach_credit_transfer": { + "type": ["null", "object"], + "properties": { + "bank_name": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "routing_number": { + "type": ["null", "string"] + }, + "swift_code": { + "type": ["null", "string"] + }, + "refund_account_holder_type": { + "type": ["null", "string"] + }, + "refund_account_holder_name": { + "type": ["null", "string"] + }, + "refund_account_number": { + "type": ["null", "string"] + }, + "refund_routing_number": { + "type": ["null", "string"] + }, + "account_number": { + "type": ["null", "string"] + } + } + }, + "customer": { + "type": ["null", "string"] + }, + "address_zip_check": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "address_state": { + "type": ["null", "string"] + }, + "alipay": { + "type": ["null", "object"], + "properties": {} + }, + "bancontact": { + "type": ["null", "object"], + "properties": {} + }, + "eps": { + "type": ["null", "object"], + "properties": {} + }, + "ideal": { + "type": ["null", "object"], + "properties": {} + }, + "multibanco": { + "type": ["null", "object"], + "properties": {} + }, + "redirect": { + "type": ["null", "object"], + "properties": { + "failure_reason": { + "type": ["null", "string"] + }, + "return_url": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "url": { + "type": ["null", "string"] + } + } + } + } + } + ] + }, + "delinquent": { + "type": ["null", "boolean"] + }, + "description": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "default_source": { + "type": ["null", "string"] + }, + "cards": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "metadata": { + "type": ["null", "object"], + "properties": {} + }, + "object": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "dynamic_last4": { + "type": ["null", "string"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "last4": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, + "brand": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "customer": { + "type": ["null", "string"] + }, + "cvc_check": { + "type": ["null", "string"] + }, + "address_line2": { + "type": ["null", "string"] + }, + "address_line1": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "address_zip": { + "type": ["null", "string"] + }, + "address_city": { + "type": ["null", "string"] + }, + "address_country": { + "type": ["null", "string"] + }, + "address_line1_check": { + "type": ["null", "string"] + }, + "tokenization_method": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "address_state": { + "type": ["null", "string"] + }, + "address_zip_check": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } + } + } + }, + "email": { + "type": ["null", "string"] + }, + "default_card": { + "type": ["null", "string"] + }, + "subscriptions": { + "type": ["null", "object"], + "properties": { + "object": { + "type": ["null", "string"] + }, + "data": { + "type": ["null", "array"] + }, + "has_more": { + "type": ["null", "boolean"] + }, + "total_count": { + "type": ["null", "number"] + }, + "url": { + "type": ["null", "string"] + } } }, "discount": { "type": ["null", "object"], "properties": { - "end": { "type": ["null", "integer"] }, + "end": { + "type": ["null", "integer"] + }, "coupon": { "type": ["null", "object"], "properties": { @@ -4813,51 +6061,119 @@ "type": ["null", "object"], "properties": {} }, - "valid": { "type": ["null", "boolean"] }, - "livemode": { "type": ["null", "boolean"] }, - "amount_off": { "type": ["null", "integer"] }, - "redeem_by": { "type": ["null", "integer"] }, - "duration_in_months": { "type": ["null", "integer"] }, - "percent_off_precise": { "type": ["null", "number"] }, - "max_redemptions": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "times_redeemed": { "type": ["null", "integer"] }, - "id": { "type": ["null", "string"] }, - "duration": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "percent_off": { "type": ["null", "number"] }, - "created": { "type": ["null", "integer"] } - } - }, - "customer": { "type": ["null", "string"] }, - "start": { "type": ["null", "integer"] }, - "object": { "type": ["null", "string"] }, - "subscription": { "type": ["null", "string"] } - } - }, - "account_balance": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, - "invoice_prefix": { "type": ["null", "string"] }, - "tax_info_verification": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "updated": { "type": ["null", "integer"] }, - "tax_info": { "type": ["null", "string"] }, - "test_clock": { "type": ["null", "string"] }, - "is_deleted": { "type": ["null", "boolean"] } + "valid": { + "type": ["null", "boolean"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "amount_off": { + "type": ["null", "integer"] + }, + "redeem_by": { + "type": ["null", "integer"] + }, + "duration_in_months": { + "type": ["null", "integer"] + }, + "percent_off_precise": { + "type": ["null", "number"] + }, + "max_redemptions": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "times_redeemed": { + "type": ["null", "integer"] + }, + "id": { + "type": ["null", "string"] + }, + "duration": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "percent_off": { + "type": ["null", "number"] + }, + "created": { + "type": ["null", "integer"] + } + } + }, + "customer": { + "type": ["null", "string"] + }, + "start": { + "type": ["null", "integer"] + }, + "object": { + "type": ["null", "string"] + }, + "subscription": { + "type": ["null", "string"] + } + } + }, + "account_balance": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "invoice_prefix": { + "type": ["null", "string"] + }, + "tax_info_verification": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "updated": { + "type": ["null", "integer"] + }, + "tax_info": { + "type": ["null", "string"] + }, + "test_clock": { + "type": ["null", "string"] + }, + "is_deleted": { + "type": ["null", "boolean"] + } } }, "eps": { "additionalProperties": true, "type": ["null", "object"], - "properties": { "bank": { "type": ["null", "string"] } } + "properties": { + "bank": { + "type": ["null", "string"] + } + } }, "fpx": { "additionalProperties": true, "type": ["null", "object"], - "properties": { "bank": { "type": ["null", "string"] } } + "properties": { + "bank": { + "type": ["null", "string"] + } + } }, "giropay": { "additionalProperties": true, @@ -4867,55 +6183,92 @@ "additionalProperties": true, "type": ["null", "object"] }, - "id": { "type": ["null", "string"] }, + "id": { + "type": ["null", "string"] + }, "ideal": { "additionalProperties": true, "type": ["null", "object"], "properties": { - "bank": { "type": ["null", "string"] }, - "bic": { "type": ["null", "string"] } + "bank": { + "type": ["null", "string"] + }, + "bic": { + "type": ["null", "string"] + } } }, "interac_present": { "additionalProperties": true, "type": ["null", "object"] }, - "livemode": { "type": ["null", "boolean"] }, + "livemode": { + "type": ["null", "boolean"] + }, "metadata": { "additionalProperties": true, "type": ["null", "object"] }, - "object": { "type": ["null", "string"] }, - "oxxo": { "additionalProperties": true, "type": ["null", "object"] }, + "object": { + "type": ["null", "string"] + }, + "oxxo": { + "additionalProperties": true, + "type": ["null", "object"] + }, "p24": { "type": ["null", "object"], "additionalProperties": true, - "properties": { "bank": { "type": ["null", "string"] } } + "properties": { + "bank": { + "type": ["null", "string"] + } + } }, "sepa_debit": { "type": ["null", "object"], "additionalProperties": true, "properties": { - "bank_code": { "type": ["null", "string"] }, - "branch_code": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, + "bank_code": { + "type": ["null", "string"] + }, + "branch_code": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, "generated_from": { "type": ["null", "object"], "properties": { - "charge": { "type": ["null", "string"] }, - "setup_attempt": { "type": ["null", "string"] } + "charge": { + "type": ["null", "string"] + }, + "setup_attempt": { + "type": ["null", "string"] + } } }, - "last4": { "type": ["null", "string"] } + "last4": { + "type": ["null", "string"] + } } }, "sofort": { "type": ["null", "object"], "additionalProperties": true, - "properties": { "country": { "type": ["null", "string"] } } + "properties": { + "country": { + "type": ["null", "string"] + } + } }, - "type": { "type": ["null", "string"] } + "type": { + "type": ["null", "string"] + } } }, "supported_sync_modes": ["full_refresh", "incremental"], @@ -5465,34 +6818,75 @@ "items": { "type": ["null", "object"], "properties": { - "fee": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "source": { "type": ["null", "string"] }, + "fee": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "source": { + "type": ["null", "string"] + }, "fee_details": { "type": ["null", "array"], "items": { "properties": { - "application": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] }, - "description": { "type": ["null", "string"] }, - "amount": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] } + "application": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + } }, "type": ["null", "object"] } }, - "available_on": { "type": ["null", "integer"] }, - "status": { "type": ["null", "string"] }, - "description": { "type": ["null", "string"] }, - "net": { "type": ["null", "integer"] }, - "exchange_rate": { "type": ["null", "number"] }, - "type": { "type": ["null", "string"] }, - "sourced_transfers": { "items": {}, "type": ["null", "array"] }, - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "amount": { "type": ["null", "integer"] }, - "reporting_category": { "type": ["null", "string"] } + "available_on": { + "type": ["null", "integer"] + }, + "status": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "net": { + "type": ["null", "integer"] + }, + "exchange_rate": { + "type": ["null", "number"] + }, + "type": { + "type": ["null", "string"] + }, + "sourced_transfers": { + "items": {}, + "type": ["null", "array"] + }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "amount": { + "type": ["null", "integer"] + }, + "reporting_category": { + "type": ["null", "string"] + } } }, "type": ["null", "array"] @@ -5500,8 +6894,12 @@ "card": { "type": ["null", "object"], "properties": { - "brand": { "type": ["null", "string"] }, - "cancellation_reason": { "type": ["null", "string"] }, + "brand": { + "type": ["null", "string"] + }, + "cancellation_reason": { + "type": ["null", "string"] + }, "cardholder": { "type": ["null", "object"], "properties": { @@ -5511,63 +6909,115 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } } } }, "company": { "type": ["null", "object"], - "properties": { "tax_id_provided": { "type": "boolean" } } + "properties": { + "tax_id_provided": { + "type": "boolean" + } + } + }, + "created": { + "type": ["null", "integer"] + }, + "updated": { + "type": ["null", "integer"] + }, + "email": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "updated": { "type": ["null", "integer"] }, - "email": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, "individual": { "type": ["null", "object"], "properties": { "dob": { "type": ["null", "object"], "properties": { - "day": { "type": ["null", "integer"] }, - "month": { "type": ["null", "integer"] }, - "year": { "type": ["null", "integer"] } + "day": { + "type": ["null", "integer"] + }, + "month": { + "type": ["null", "integer"] + }, + "year": { + "type": ["null", "integer"] + } } }, - "first_name": { "type": ["null", "string"] }, - "last_name": { "type": ["null", "string"] }, + "first_name": { + "type": ["null", "string"] + }, + "last_name": { + "type": ["null", "string"] + }, "verification": { "type": ["null", "object"], "properties": { "document": { "type": ["null", "object"], "properties": { - "back": { "type": ["null", "string"] }, - "front": { "type": ["null", "string"] } + "back": { + "type": ["null", "string"] + }, + "front": { + "type": ["null", "string"] + } } } } } } }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"] }, - "name": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "phone_number": { "type": ["null", "string"] }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"] + }, + "name": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + }, "requirements": { "type": ["null", "object"], "properties": { - "disabled_reason": { "type": ["null", "string"] }, + "disabled_reason": { + "type": ["null", "string"] + }, "past_due": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, @@ -5576,42 +7026,78 @@ "properties": { "allowed_categories": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "blocked_categories": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "spending_limits": { "type": ["null", "array"], - "items": { "type": ["null", "object"] } + "items": { + "type": ["null", "object"] + } }, - "spending_limits_currency": { "type": ["null", "string"] } + "spending_limits_currency": { + "type": ["null", "string"] + } } }, - "status": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] }, + "status": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, "preferred_locales": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, - "created": { "type": ["null", "integer"] }, - "updated": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "cvc": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "exp_year": { "type": ["null", "integer"] }, - "id": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, + "created": { + "type": ["null", "integer"] + }, + "updated": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "cvc": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "id": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, "metadata": { "type": ["null", "object"], "additionalProperties": true }, - "number": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, + "number": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, "replaced_by": { "type": ["null", "object"], "additionalProperties": true @@ -5620,7 +7106,9 @@ "type": ["null", "object"], "additionalProperties": true }, - "replacement_reason": { "type": ["null", "string"] }, + "replacement_reason": { + "type": ["null", "string"] + }, "shipping": { "type": ["null", "object"], "additionalProperties": true, @@ -5628,22 +7116,50 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "carrier": { "type": ["null", "string"] }, - "eta": { "type": ["null", "integer"] }, - "name": { "type": ["null", "string"] }, - "service": { "type": ["null", "string"] }, - "status": { "type": ["null", "string"] }, - "tracking_number": { "type": ["null", "string"] }, - "tracking_url": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } + "carrier": { + "type": ["null", "string"] + }, + "eta": { + "type": ["null", "integer"] + }, + "name": { + "type": ["null", "string"] + }, + "service": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "tracking_number": { + "type": ["null", "string"] + }, + "tracking_url": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } } }, "spending_controls": { @@ -5651,21 +7167,33 @@ "properties": { "allowed_categories": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "blocked_categories": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "spending_limits": { "type": ["null", "array"], - "items": { "type": ["null", "object"] } + "items": { + "type": ["null", "object"] + } }, - "spending_limits_currency": { "type": ["null", "string"] } + "spending_limits_currency": { + "type": ["null", "string"] + } } }, - "status": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } + "status": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } } }, "cardholder": { @@ -5943,9 +7471,15 @@ "flight": { "type": ["null", "object"], "properties": { - "departure_at": { "type": ["null", "integer"] }, - "passenger_name": { "type": ["null", "string"] }, - "refundable": { "type": ["null", "boolean"] }, + "departure_at": { + "type": ["null", "integer"] + }, + "passenger_name": { + "type": ["null", "string"] + }, + "refundable": { + "type": ["null", "boolean"] + }, "segments": { "type": ["null", "array"], "items": { @@ -5954,12 +7488,18 @@ "arrival_airport_code": { "type": ["null", "string"] }, - "carrier": { "type": ["null", "string"] }, + "carrier": { + "type": ["null", "string"] + }, "departure_airport_code": { "type": ["null", "string"] }, - "flight_number": { "type": ["null", "string"] }, - "service_class": { "type": ["null", "string"] }, + "flight_number": { + "type": ["null", "string"] + }, + "service_class": { + "type": ["null", "string"] + }, "stopover_allowed": { "type": ["null", "boolean"] } @@ -5967,38 +7507,62 @@ } } }, - "travel_agency": { "type": ["null", "string"] } + "travel_agency": { + "type": ["null", "string"] + } } }, "fuel": { "type": ["null", "object"], "properties": { - "type": { "type": ["null", "string"] }, - "unit": { "type": ["null", "string"] }, - "unit_cost_decimal": { "type": ["null", "string"] }, - "volume_decimal": { "type": ["null", "string"] } + "type": { + "type": ["null", "string"] + }, + "unit": { + "type": ["null", "string"] + }, + "unit_cost_decimal": { + "type": ["null", "string"] + }, + "volume_decimal": { + "type": ["null", "string"] + } } }, "lodging": { "type": ["null", "object"], "properties": { - "check_in_at": { "type": ["null", "integer"] }, - "nights": { "type": ["null", "integer"] } + "check_in_at": { + "type": ["null", "integer"] + }, + "nights": { + "type": ["null", "integer"] + } } }, "receipt": { "items": { "type": ["null", "object"], "properties": { - "description": { "type": ["null", "string"] }, - "quantity": { "type": ["null", "number"] }, - "total": { "type": ["null", "integer"] }, - "unit_cost": { "type": ["null", "integer"] } + "description": { + "type": ["null", "string"] + }, + "quantity": { + "type": ["null", "number"] + }, + "total": { + "type": ["null", "integer"] + }, + "unit_cost": { + "type": ["null", "integer"] + } } }, "type": ["null", "array"] }, - "reference": { "type": ["null", "string"] } + "reference": { + "type": ["null", "string"] + } } } } @@ -6042,36 +7606,69 @@ "json_schema": { "type": ["null", "object"], "properties": { - "metadata": { "type": ["null", "object"], "properties": {} }, + "metadata": { + "type": ["null", "object"], + "properties": {} + }, "preferred_locales": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "invoice_settings": { "type": ["null", "object"], "properties": { "custom_fields": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } + }, + "default_payment_method": { + "type": ["null", "string"] }, - "default_payment_method": { "type": ["null", "string"] }, - "footer": { "type": ["null", "string"] } + "footer": { + "type": ["null", "string"] + } } }, - "name": { "type": ["null", "string"] }, - "tax_exempt": { "type": ["null", "string"] }, - "next_invoice_sequence": { "type": ["null", "integer"] }, - "balance": { "type": ["null", "integer"] }, - "phone": { "type": ["null", "string"] }, + "name": { + "type": ["null", "string"] + }, + "tax_exempt": { + "type": ["null", "string"] + }, + "next_invoice_sequence": { + "type": ["null", "integer"] + }, + "balance": { + "type": ["null", "integer"] + }, + "phone": { + "type": ["null", "string"] + }, "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, "shipping": { @@ -6080,16 +7677,32 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "name": { "type": ["null", "string"] }, - "phone": { "type": ["null", "string"] } + "name": { + "type": ["null", "string"] + }, + "phone": { + "type": ["null", "string"] + } } }, "sources": { @@ -6103,121 +7716,272 @@ "type": ["null", "object"], "properties": {} }, - "type": { "type": ["null", "string"] }, - "address_zip": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, + "type": { + "type": ["null", "string"] + }, + "address_zip": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, "card": { "type": ["null", "object"], "properties": { - "fingerprint": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "dynamic_last4": { "type": ["null", "string"] }, - "address_line1_check": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "tokenization_method": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "exp_year": { "type": ["null", "integer"] }, - "three_d_secure": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, - "brand": { "type": ["null", "string"] }, - "cvc_check": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "address_zip_check": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } + "fingerprint": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + }, + "dynamic_last4": { + "type": ["null", "string"] + }, + "address_line1_check": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "tokenization_method": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "three_d_secure": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, + "brand": { + "type": ["null", "string"] + }, + "cvc_check": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "address_zip_check": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } } }, - "statement_descriptor": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, - "address_country": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, - "dynamic_last4": { "type": ["null", "string"] }, - "exp_year": { "type": ["null", "integer"] }, - "last4": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "brand": { "type": ["null", "string"] }, - "address_line2": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "amount": { "type": ["null", "integer"] }, - "cvc_check": { "type": ["null", "string"] }, - "usage": { "type": ["null", "string"] }, - "address_line1": { "type": ["null", "string"] }, + "statement_descriptor": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "address_country": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, + "dynamic_last4": { + "type": ["null", "string"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "last4": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "brand": { + "type": ["null", "string"] + }, + "address_line2": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "integer"] + }, + "cvc_check": { + "type": ["null", "string"] + }, + "usage": { + "type": ["null", "string"] + }, + "address_line1": { + "type": ["null", "string"] + }, "owner": { "type": ["null", "object"], "properties": { - "verified_address": { "type": ["null", "string"] }, - "email": { "type": ["null", "string"] }, + "verified_address": { + "type": ["null", "string"] + }, + "email": { + "type": ["null", "string"] + }, "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "verified_email": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "phone": { "type": ["null", "string"] }, - "verified_name": { "type": ["null", "string"] }, - "verified_phone": { "type": ["null", "string"] } + "verified_email": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "phone": { + "type": ["null", "string"] + }, + "verified_name": { + "type": ["null", "string"] + }, + "verified_phone": { + "type": ["null", "string"] + } } }, - "tokenization_method": { "type": ["null", "string"] }, - "client_secret": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "address_city": { "type": ["null", "string"] }, - "currency": { "type": ["null", "string"] }, - "address_line1_check": { "type": ["null", "string"] }, + "tokenization_method": { + "type": ["null", "string"] + }, + "client_secret": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "address_city": { + "type": ["null", "string"] + }, + "currency": { + "type": ["null", "string"] + }, + "address_line1_check": { + "type": ["null", "string"] + }, "receiver": { "type": ["null", "object"], "properties": { "refund_attributes_method": { "type": ["null", "string"] }, - "amount_returned": { "type": ["null", "integer"] }, - "amount_received": { "type": ["null", "integer"] }, + "amount_returned": { + "type": ["null", "integer"] + }, + "amount_received": { + "type": ["null", "integer"] + }, "refund_attributes_status": { "type": ["null", "string"] }, - "address": { "type": ["null", "string"] }, - "amount_charged": { "type": ["null", "integer"] } + "address": { + "type": ["null", "string"] + }, + "amount_charged": { + "type": ["null", "integer"] + } } }, - "flow": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, + "flow": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, "ach_credit_transfer": { "type": ["null", "object"], "properties": { - "bank_name": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "routing_number": { "type": ["null", "string"] }, - "swift_code": { "type": ["null", "string"] }, + "bank_name": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "routing_number": { + "type": ["null", "string"] + }, + "swift_code": { + "type": ["null", "string"] + }, "refund_account_holder_type": { "type": ["null", "string"] }, "refund_account_holder_name": { "type": ["null", "string"] }, - "refund_account_number": { "type": ["null", "string"] }, - "refund_routing_number": { "type": ["null", "string"] }, - "account_number": { "type": ["null", "string"] } + "refund_account_number": { + "type": ["null", "string"] + }, + "refund_routing_number": { + "type": ["null", "string"] + }, + "account_number": { + "type": ["null", "string"] + } } }, - "customer": { "type": ["null", "string"] }, - "address_zip_check": { "type": ["null", "string"] }, - "status": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "address_state": { "type": ["null", "string"] }, - "alipay": { "type": ["null", "object"], "properties": {} }, + "customer": { + "type": ["null", "string"] + }, + "address_zip_check": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "address_state": { + "type": ["null", "string"] + }, + "alipay": { + "type": ["null", "object"], + "properties": {} + }, "bancontact": { "type": ["null", "object"], "properties": {} }, - "eps": { "type": ["null", "object"], "properties": {} }, - "ideal": { "type": ["null", "object"], "properties": {} }, + "eps": { + "type": ["null", "object"], + "properties": {} + }, + "ideal": { + "type": ["null", "object"], + "properties": {} + }, "multibanco": { "type": ["null", "object"], "properties": {} @@ -6225,10 +7989,18 @@ "redirect": { "type": ["null", "object"], "properties": { - "failure_reason": { "type": ["null", "string"] }, - "return_url": { "type": ["null", "string"] }, - "status": { "type": ["null", "string"] }, - "url": { "type": ["null", "string"] } + "failure_reason": { + "type": ["null", "string"] + }, + "return_url": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "url": { + "type": ["null", "string"] + } } } } @@ -6237,122 +8009,276 @@ { "type": ["null", "object"], "properties": { - "metadata": { "type": ["null", "object"], "properties": {} }, - "type": { "type": ["null", "string"] }, - "address_zip": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, + "metadata": { + "type": ["null", "object"], + "properties": {} + }, + "type": { + "type": ["null", "string"] + }, + "address_zip": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, "card": { "type": ["null", "object"], "properties": { - "fingerprint": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "dynamic_last4": { "type": ["null", "string"] }, - "address_line1_check": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "tokenization_method": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "exp_year": { "type": ["null", "integer"] }, - "three_d_secure": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, - "brand": { "type": ["null", "string"] }, - "cvc_check": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "address_zip_check": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } - } - }, - "statement_descriptor": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, - "address_country": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, - "dynamic_last4": { "type": ["null", "string"] }, - "exp_year": { "type": ["null", "integer"] }, - "last4": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "brand": { "type": ["null", "string"] }, - "address_line2": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "amount": { "type": ["null", "integer"] }, - "cvc_check": { "type": ["null", "string"] }, - "usage": { "type": ["null", "string"] }, - "address_line1": { "type": ["null", "string"] }, + "fingerprint": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + }, + "dynamic_last4": { + "type": ["null", "string"] + }, + "address_line1_check": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "tokenization_method": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "three_d_secure": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, + "brand": { + "type": ["null", "string"] + }, + "cvc_check": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "address_zip_check": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } + } + }, + "statement_descriptor": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "address_country": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, + "dynamic_last4": { + "type": ["null", "string"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "last4": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "brand": { + "type": ["null", "string"] + }, + "address_line2": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "integer"] + }, + "cvc_check": { + "type": ["null", "string"] + }, + "usage": { + "type": ["null", "string"] + }, + "address_line1": { + "type": ["null", "string"] + }, "owner": { "type": ["null", "object"], "properties": { - "verified_address": { "type": ["null", "string"] }, - "email": { "type": ["null", "string"] }, + "verified_address": { + "type": ["null", "string"] + }, + "email": { + "type": ["null", "string"] + }, "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "verified_email": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "phone": { "type": ["null", "string"] }, - "verified_name": { "type": ["null", "string"] }, - "verified_phone": { "type": ["null", "string"] } + "verified_email": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "phone": { + "type": ["null", "string"] + }, + "verified_name": { + "type": ["null", "string"] + }, + "verified_phone": { + "type": ["null", "string"] + } } }, - "tokenization_method": { "type": ["null", "string"] }, - "client_secret": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "address_city": { "type": ["null", "string"] }, - "currency": { "type": ["null", "string"] }, - "address_line1_check": { "type": ["null", "string"] }, + "tokenization_method": { + "type": ["null", "string"] + }, + "client_secret": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "address_city": { + "type": ["null", "string"] + }, + "currency": { + "type": ["null", "string"] + }, + "address_line1_check": { + "type": ["null", "string"] + }, "receiver": { "type": ["null", "object"], "properties": { "refund_attributes_method": { "type": ["null", "string"] }, - "amount_returned": { "type": ["null", "integer"] }, - "amount_received": { "type": ["null", "integer"] }, + "amount_returned": { + "type": ["null", "integer"] + }, + "amount_received": { + "type": ["null", "integer"] + }, "refund_attributes_status": { "type": ["null", "string"] }, - "address": { "type": ["null", "string"] }, - "amount_charged": { "type": ["null", "integer"] } + "address": { + "type": ["null", "string"] + }, + "amount_charged": { + "type": ["null", "integer"] + } } }, - "flow": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, + "flow": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, "ach_credit_transfer": { "type": ["null", "object"], "properties": { - "bank_name": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "routing_number": { "type": ["null", "string"] }, - "swift_code": { "type": ["null", "string"] }, + "bank_name": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "routing_number": { + "type": ["null", "string"] + }, + "swift_code": { + "type": ["null", "string"] + }, "refund_account_holder_type": { "type": ["null", "string"] }, "refund_account_holder_name": { "type": ["null", "string"] }, - "refund_account_number": { "type": ["null", "string"] }, - "refund_routing_number": { "type": ["null", "string"] }, - "account_number": { "type": ["null", "string"] } + "refund_account_number": { + "type": ["null", "string"] + }, + "refund_routing_number": { + "type": ["null", "string"] + }, + "account_number": { + "type": ["null", "string"] + } } }, - "customer": { "type": ["null", "string"] }, - "address_zip_check": { "type": ["null", "string"] }, - "status": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "address_state": { "type": ["null", "string"] }, - "alipay": { "type": ["null", "object"], "properties": {} }, + "customer": { + "type": ["null", "string"] + }, + "address_zip_check": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "address_state": { + "type": ["null", "string"] + }, + "alipay": { + "type": ["null", "object"], + "properties": {} + }, "bancontact": { "type": ["null", "object"], "properties": {} }, - "eps": { "type": ["null", "object"], "properties": {} }, - "ideal": { "type": ["null", "object"], "properties": {} }, + "eps": { + "type": ["null", "object"], + "properties": {} + }, + "ideal": { + "type": ["null", "object"], + "properties": {} + }, "multibanco": { "type": ["null", "object"], "properties": {} @@ -6360,106 +8286,250 @@ "redirect": { "type": ["null", "object"], "properties": { - "failure_reason": { "type": ["null", "string"] }, - "return_url": { "type": ["null", "string"] }, - "status": { "type": ["null", "string"] }, - "url": { "type": ["null", "string"] } + "failure_reason": { + "type": ["null", "string"] + }, + "return_url": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "url": { + "type": ["null", "string"] + } } } } } - ] - }, - "delinquent": { "type": ["null", "boolean"] }, - "description": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "default_source": { "type": ["null", "string"] }, - "cards": { - "type": ["null", "array"], - "items": { - "type": ["null", "object"], - "properties": { - "metadata": { "type": ["null", "object"], "properties": {} }, - "object": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "dynamic_last4": { "type": ["null", "string"] }, - "exp_year": { "type": ["null", "integer"] }, - "last4": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, - "brand": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "customer": { "type": ["null", "string"] }, - "cvc_check": { "type": ["null", "string"] }, - "address_line2": { "type": ["null", "string"] }, - "address_line1": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "address_zip": { "type": ["null", "string"] }, - "address_city": { "type": ["null", "string"] }, - "address_country": { "type": ["null", "string"] }, - "address_line1_check": { "type": ["null", "string"] }, - "tokenization_method": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "address_state": { "type": ["null", "string"] }, - "address_zip_check": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } - } - } - }, - "email": { "type": ["null", "string"] }, - "default_card": { "type": ["null", "string"] }, - "subscriptions": { - "type": ["null", "object"], - "properties": { - "object": { "type": ["null", "string"] }, - "data": { "type": ["null", "array"] }, - "has_more": { "type": ["null", "boolean"] }, - "total_count": { "type": ["null", "number"] }, - "url": { "type": ["null", "string"] } + ] + }, + "delinquent": { + "type": ["null", "boolean"] + }, + "description": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "default_source": { + "type": ["null", "string"] + }, + "cards": { + "type": ["null", "array"], + "items": { + "type": ["null", "object"], + "properties": { + "metadata": { + "type": ["null", "object"], + "properties": {} + }, + "object": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "dynamic_last4": { + "type": ["null", "string"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "last4": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, + "brand": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "customer": { + "type": ["null", "string"] + }, + "cvc_check": { + "type": ["null", "string"] + }, + "address_line2": { + "type": ["null", "string"] + }, + "address_line1": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "address_zip": { + "type": ["null", "string"] + }, + "address_city": { + "type": ["null", "string"] + }, + "address_country": { + "type": ["null", "string"] + }, + "address_line1_check": { + "type": ["null", "string"] + }, + "tokenization_method": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "address_state": { + "type": ["null", "string"] + }, + "address_zip_check": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } + } + } + }, + "email": { + "type": ["null", "string"] + }, + "default_card": { + "type": ["null", "string"] + }, + "subscriptions": { + "type": ["null", "object"], + "properties": { + "object": { + "type": ["null", "string"] + }, + "data": { + "type": ["null", "array"] + }, + "has_more": { + "type": ["null", "boolean"] + }, + "total_count": { + "type": ["null", "number"] + }, + "url": { + "type": ["null", "string"] + } + } + }, + "discount": { + "type": ["null", "object"], + "properties": { + "end": { + "type": ["null", "integer"] + }, + "coupon": { + "type": ["null", "object"], + "properties": { + "metadata": { + "type": ["null", "object"], + "properties": {} + }, + "valid": { + "type": ["null", "boolean"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "amount_off": { + "type": ["null", "integer"] + }, + "redeem_by": { + "type": ["null", "integer"] + }, + "duration_in_months": { + "type": ["null", "integer"] + }, + "percent_off_precise": { + "type": ["null", "number"] + }, + "max_redemptions": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "times_redeemed": { + "type": ["null", "integer"] + }, + "id": { + "type": ["null", "string"] + }, + "duration": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "percent_off": { + "type": ["null", "number"] + }, + "created": { + "type": ["null", "integer"] + } + } + }, + "customer": { + "type": ["null", "string"] + }, + "start": { + "type": ["null", "integer"] + }, + "object": { + "type": ["null", "string"] + }, + "subscription": { + "type": ["null", "string"] + } } }, - "discount": { - "type": ["null", "object"], - "properties": { - "end": { "type": ["null", "integer"] }, - "coupon": { - "type": ["null", "object"], - "properties": { - "metadata": { "type": ["null", "object"], "properties": {} }, - "valid": { "type": ["null", "boolean"] }, - "livemode": { "type": ["null", "boolean"] }, - "amount_off": { "type": ["null", "integer"] }, - "redeem_by": { "type": ["null", "integer"] }, - "duration_in_months": { "type": ["null", "integer"] }, - "percent_off_precise": { "type": ["null", "number"] }, - "max_redemptions": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "times_redeemed": { "type": ["null", "integer"] }, - "id": { "type": ["null", "string"] }, - "duration": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "percent_off": { "type": ["null", "number"] }, - "created": { "type": ["null", "integer"] } - } - }, - "customer": { "type": ["null", "string"] }, - "start": { "type": ["null", "integer"] }, - "object": { "type": ["null", "string"] }, - "subscription": { "type": ["null", "string"] } - } - }, - "account_balance": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, - "invoice_prefix": { "type": ["null", "string"] }, - "tax_info_verification": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "updated": { "type": ["null", "integer"] }, - "tax_info": { "type": ["null", "string"] }, - "test_clock": { "type": ["null", "string"] }, - "is_deleted": { "type": ["null", "boolean"] } + "account_balance": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "invoice_prefix": { + "type": ["null", "string"] + }, + "tax_info_verification": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "updated": { + "type": ["null", "integer"] + }, + "tax_info": { + "type": ["null", "string"] + }, + "test_clock": { + "type": ["null", "string"] + }, + "is_deleted": { + "type": ["null", "boolean"] + } } }, "supported_sync_modes": ["full_refresh", "incremental"], @@ -6479,63 +8549,115 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } } } }, "company": { "type": ["null", "object"], - "properties": { "tax_id_provided": { "type": "boolean" } } + "properties": { + "tax_id_provided": { + "type": "boolean" + } + } + }, + "created": { + "type": ["null", "integer"] + }, + "updated": { + "type": ["null", "integer"] + }, + "email": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "updated": { "type": ["null", "integer"] }, - "email": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, "individual": { "type": ["null", "object"], "properties": { "dob": { "type": ["null", "object"], "properties": { - "day": { "type": ["null", "integer"] }, - "month": { "type": ["null", "integer"] }, - "year": { "type": ["null", "integer"] } + "day": { + "type": ["null", "integer"] + }, + "month": { + "type": ["null", "integer"] + }, + "year": { + "type": ["null", "integer"] + } } }, - "first_name": { "type": ["null", "string"] }, - "last_name": { "type": ["null", "string"] }, + "first_name": { + "type": ["null", "string"] + }, + "last_name": { + "type": ["null", "string"] + }, "verification": { "type": ["null", "object"], "properties": { "document": { "type": ["null", "object"], "properties": { - "back": { "type": ["null", "string"] }, - "front": { "type": ["null", "string"] } + "back": { + "type": ["null", "string"] + }, + "front": { + "type": ["null", "string"] + } } } } } } }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"] }, - "name": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "phone_number": { "type": ["null", "string"] }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"] + }, + "name": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + }, "requirements": { "type": ["null", "object"], "properties": { - "disabled_reason": { "type": ["null", "string"] }, + "disabled_reason": { + "type": ["null", "string"] + }, "past_due": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, @@ -6544,24 +8666,38 @@ "properties": { "allowed_categories": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "blocked_categories": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "spending_limits": { "type": ["null", "array"], - "items": { "type": ["null", "object"] } + "items": { + "type": ["null", "object"] + } }, - "spending_limits_currency": { "type": ["null", "string"] } + "spending_limits_currency": { + "type": ["null", "string"] + } } }, - "status": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] }, + "status": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, "preferred_locales": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, @@ -6588,146 +8724,296 @@ "stripe_report": { "description": "The ID of the fraud report from Stripe.", "type": ["null", "string"] - } - } - }, - "transfer_group": { - "description": "The transfer group of the charge.", - "type": ["null", "string"] - }, - "on_behalf_of": { - "description": "The ID of the account on behalf of which the charge is made.", - "type": ["null", "string"] - }, - "review": { - "description": "A boolean indicating if the charge is under review.", - "type": ["null", "string"] - }, - "failure_message": { - "description": "The failure error message for the charge.", - "type": ["null", "string"] - }, - "receipt_email": { - "description": "The email address to send receipt of the charge.", - "type": ["null", "string"] - }, - "statement_descriptor": { - "description": "The statement descriptor for the charge.", - "type": ["null", "string"] - }, - "source": { - "description": "Details of the payment source for the charge.", - "type": ["null", "object"], - "properties": { - "metadata": { - "description": "Metadata related to the payment source.", - "type": ["null", "object"], - "properties": {} + } + } + }, + "transfer_group": { + "description": "The transfer group of the charge.", + "type": ["null", "string"] + }, + "on_behalf_of": { + "description": "The ID of the account on behalf of which the charge is made.", + "type": ["null", "string"] + }, + "review": { + "description": "A boolean indicating if the charge is under review.", + "type": ["null", "string"] + }, + "failure_message": { + "description": "The failure error message for the charge.", + "type": ["null", "string"] + }, + "receipt_email": { + "description": "The email address to send receipt of the charge.", + "type": ["null", "string"] + }, + "statement_descriptor": { + "description": "The statement descriptor for the charge.", + "type": ["null", "string"] + }, + "source": { + "description": "Details of the payment source for the charge.", + "type": ["null", "object"], + "properties": { + "metadata": { + "description": "Metadata related to the payment source.", + "type": ["null", "object"], + "properties": {} + }, + "type": { + "type": ["null", "string"] + }, + "address_zip": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "card": { + "description": "Details of the credit/debit card source.", + "type": ["null", "object"], + "properties": { + "fingerprint": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + }, + "dynamic_last4": { + "type": ["null", "string"] + }, + "address_line1_check": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "tokenization_method": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "three_d_secure": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, + "brand": { + "type": ["null", "string"] + }, + "cvc_check": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "address_zip_check": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } + } + }, + "statement_descriptor": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "address_country": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, + "dynamic_last4": { + "type": ["null", "string"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "last4": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "brand": { + "type": ["null", "string"] + }, + "address_line2": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "integer"] + }, + "cvc_check": { + "type": ["null", "string"] + }, + "usage": { + "type": ["null", "string"] + }, + "address_line1": { + "type": ["null", "string"] }, - "type": { "type": ["null", "string"] }, - "address_zip": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "card": { - "description": "Details of the credit/debit card source.", - "type": ["null", "object"], - "properties": { - "fingerprint": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "dynamic_last4": { "type": ["null", "string"] }, - "address_line1_check": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "tokenization_method": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "exp_year": { "type": ["null", "integer"] }, - "three_d_secure": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, - "brand": { "type": ["null", "string"] }, - "cvc_check": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "address_zip_check": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } - } - }, - "statement_descriptor": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, - "address_country": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, - "dynamic_last4": { "type": ["null", "string"] }, - "exp_year": { "type": ["null", "integer"] }, - "last4": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "brand": { "type": ["null", "string"] }, - "address_line2": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "amount": { "type": ["null", "integer"] }, - "cvc_check": { "type": ["null", "string"] }, - "usage": { "type": ["null", "string"] }, - "address_line1": { "type": ["null", "string"] }, "owner": { "description": "Details of the owner of the payment source.", "type": ["null", "object"], "properties": { - "verified_address": { "type": ["null", "string"] }, - "email": { "type": ["null", "string"] }, + "verified_address": { + "type": ["null", "string"] + }, + "email": { + "type": ["null", "string"] + }, "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } - } - }, - "verified_email": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "phone": { "type": ["null", "string"] }, - "verified_name": { "type": ["null", "string"] }, - "verified_phone": { "type": ["null", "string"] } - } - }, - "tokenization_method": { "type": ["null", "string"] }, - "client_secret": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "address_city": { "type": ["null", "string"] }, - "currency": { "type": ["null", "string"] }, - "address_line1_check": { "type": ["null", "string"] }, + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } + } + }, + "verified_email": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "phone": { + "type": ["null", "string"] + }, + "verified_name": { + "type": ["null", "string"] + }, + "verified_phone": { + "type": ["null", "string"] + } + } + }, + "tokenization_method": { + "type": ["null", "string"] + }, + "client_secret": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "address_city": { + "type": ["null", "string"] + }, + "currency": { + "type": ["null", "string"] + }, + "address_line1_check": { + "type": ["null", "string"] + }, "receiver": { "description": "Details of the receiver of the payment source.", "type": ["null", "object"], "properties": { - "refund_attributes_method": { "type": ["null", "string"] }, - "amount_returned": { "type": ["null", "integer"] }, - "amount_received": { "type": ["null", "integer"] }, - "refund_attributes_status": { "type": ["null", "string"] }, - "address": { "type": ["null", "string"] }, - "amount_charged": { "type": ["null", "integer"] } + "refund_attributes_method": { + "type": ["null", "string"] + }, + "amount_returned": { + "type": ["null", "integer"] + }, + "amount_received": { + "type": ["null", "integer"] + }, + "refund_attributes_status": { + "type": ["null", "string"] + }, + "address": { + "type": ["null", "string"] + }, + "amount_charged": { + "type": ["null", "integer"] + } } }, - "flow": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, + "flow": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, "ach_credit_transfer": { "description": "Details of the ACH credit transfer source.", "type": ["null", "object"], "properties": { - "bank_name": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "routing_number": { "type": ["null", "string"] }, - "swift_code": { "type": ["null", "string"] }, - "refund_account_holder_type": { "type": ["null", "string"] }, - "refund_account_holder_name": { "type": ["null", "string"] }, - "refund_account_number": { "type": ["null", "string"] }, - "refund_routing_number": { "type": ["null", "string"] }, - "account_number": { "type": ["null", "string"] } - } - }, - "customer": { "type": ["null", "string"] }, - "address_zip_check": { "type": ["null", "string"] }, - "status": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "address_state": { "type": ["null", "string"] }, + "bank_name": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "routing_number": { + "type": ["null", "string"] + }, + "swift_code": { + "type": ["null", "string"] + }, + "refund_account_holder_type": { + "type": ["null", "string"] + }, + "refund_account_holder_name": { + "type": ["null", "string"] + }, + "refund_account_number": { + "type": ["null", "string"] + }, + "refund_routing_number": { + "type": ["null", "string"] + }, + "account_number": { + "type": ["null", "string"] + } + } + }, + "customer": { + "type": ["null", "string"] + }, + "address_zip_check": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "address_state": { + "type": ["null", "string"] + }, "alipay": { "description": "Details of the Alipay source.", "type": ["null", "object"], @@ -6757,10 +9043,18 @@ "description": "Details of the redirect setup for the payment source.", "type": ["null", "object"], "properties": { - "failure_reason": { "type": ["null", "string"] }, - "return_url": { "type": ["null", "string"] }, - "status": { "type": ["null", "string"] }, - "url": { "type": ["null", "string"] } + "failure_reason": { + "type": ["null", "string"] + }, + "return_url": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "url": { + "type": ["null", "string"] + } } } } @@ -6781,12 +9075,24 @@ "description": "Details of the outcome of the charge.", "type": ["null", "object"], "properties": { - "type": { "type": ["null", "string"] }, - "seller_message": { "type": ["null", "string"] }, - "reason": { "type": ["null", "string"] }, - "risk_level": { "type": ["null", "string"] }, - "network_status": { "type": ["null", "string"] }, - "risk_score": { "type": ["null", "integer"] } + "type": { + "type": ["null", "string"] + }, + "seller_message": { + "type": ["null", "string"] + }, + "reason": { + "type": ["null", "string"] + }, + "risk_level": { + "type": ["null", "string"] + }, + "network_status": { + "type": ["null", "string"] + }, + "risk_score": { + "type": ["null", "integer"] + } } }, "status": { @@ -6866,11 +9172,21 @@ "description": "Details of refunds against the charge.", "type": ["null", "object"], "properties": { - "object": { "type": ["null", "string"] }, - "data": { "type": ["null", "array"] }, - "has_more": { "type": ["null", "boolean"] }, - "total_count": { "type": ["null", "number"] }, - "url": { "type": ["null", "string"] } + "object": { + "type": ["null", "string"] + }, + "data": { + "type": ["null", "array"] + }, + "has_more": { + "type": ["null", "boolean"] + }, + "total_count": { + "type": ["null", "number"] + }, + "url": { + "type": ["null", "string"] + } } }, "application_fee": { @@ -6886,29 +9202,75 @@ "type": ["null", "object"], "properties": {} }, - "exp_month": { "type": ["null", "integer"] }, - "address_state": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "address_line1_check": { "type": ["null", "string"] }, - "address_line1": { "type": ["null", "string"] }, - "exp_year": { "type": ["null", "integer"] }, - "tokenization_method": { "type": ["null", "string"] }, - "address_country": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "address_city": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "address_line2": { "type": ["null", "string"] }, - "customer": { "type": ["null", "string"] }, - "brand": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "dynamic_last4": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, - "address_zip": { "type": ["null", "string"] }, - "address_zip_check": { "type": ["null", "string"] }, - "cvc_check": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } + "exp_month": { + "type": ["null", "integer"] + }, + "address_state": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "address_line1_check": { + "type": ["null", "string"] + }, + "address_line1": { + "type": ["null", "string"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "tokenization_method": { + "type": ["null", "string"] + }, + "address_country": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "address_city": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + }, + "address_line2": { + "type": ["null", "string"] + }, + "customer": { + "type": ["null", "string"] + }, + "brand": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "dynamic_last4": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, + "address_zip": { + "type": ["null", "string"] + }, + "address_zip_check": { + "type": ["null", "string"] + }, + "cvc_check": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } } }, "payment_method_details": { @@ -6919,58 +9281,108 @@ "description": "Details of the ACH credit transfer payment method.", "type": ["null", "object"], "properties": { - "account_number": { "type": ["null", "string"] }, - "bank_name": { "type": ["null", "string"] }, - "routing_number": { "type": ["null", "string"] }, - "swift_code": { "type": ["null", "string"] } + "account_number": { + "type": ["null", "string"] + }, + "bank_name": { + "type": ["null", "string"] + }, + "routing_number": { + "type": ["null", "string"] + }, + "swift_code": { + "type": ["null", "string"] + } } }, "ach_debit": { "description": "Details of the ACH debit payment method.", "type": ["null", "object"], "properties": { - "account_holder_type": { "type": ["null", "string"] }, - "bank_name": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "routing_number": { "type": ["null", "string"] } + "account_holder_type": { + "type": ["null", "string"] + }, + "bank_name": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + }, + "routing_number": { + "type": ["null", "string"] + } } }, - "alipay": { "type": ["null", "object"] }, + "alipay": { + "type": ["null", "object"] + }, "bancontact": { "description": "Details of the Bancontact payment method.", "type": ["null", "object"], "properties": { - "bank_code": { "type": ["null", "string"] }, - "bank_name": { "type": ["null", "string"] }, - "bic": { "type": ["null", "string"] }, - "iban_last4": { "type": ["null", "string"] }, - "preferred_language": { "type": ["null", "string"] }, - "verified_name": { "type": ["null", "string"] } + "bank_code": { + "type": ["null", "string"] + }, + "bank_name": { + "type": ["null", "string"] + }, + "bic": { + "type": ["null", "string"] + }, + "iban_last4": { + "type": ["null", "string"] + }, + "preferred_language": { + "type": ["null", "string"] + }, + "verified_name": { + "type": ["null", "string"] + } } }, "card": { "description": "Details of the credit/debit card payment method.", "type": ["null", "object"], "properties": { - "brand": { "type": ["null", "string"] }, + "brand": { + "type": ["null", "string"] + }, "checks": { "description": "Check details for the card payment.", "type": ["null", "object"], "properties": { - "address_line1_check": { "type": ["null", "string"] }, + "address_line1_check": { + "type": ["null", "string"] + }, "address_postal_code_check": { "type": ["null", "string"] }, - "cvc_check": { "type": ["null", "string"] } + "cvc_check": { + "type": ["null", "string"] + } } }, - "country": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "exp_year": { "type": ["null", "integer"] }, - "fingerprint": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, + "country": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, "installments": { "description": "Details of the installments plan for payment.", "type": ["null", "object"], @@ -6979,22 +9391,38 @@ "description": "Details of the installment plan.", "type": ["null", "object"], "properties": { - "count": { "type": ["null", "integer"] }, - "interval": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } + "count": { + "type": ["null", "integer"] + }, + "interval": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } } } } }, - "last4": { "type": ["null", "string"] }, - "network": { "type": ["null", "string"] }, + "last4": { + "type": ["null", "string"] + }, + "network": { + "type": ["null", "string"] + }, "three_d_secure": { "description": "Details of the 3D Secure authentication for payment.", "type": ["null", "object"], "properties": { - "authenticated": { "type": ["null", "boolean"] }, - "succeeded": { "type": ["null", "boolean"] }, - "version": { "type": ["null", "string"] } + "authenticated": { + "type": ["null", "boolean"] + }, + "succeeded": { + "type": ["null", "boolean"] + }, + "version": { + "type": ["null", "string"] + } } }, "wallet": { @@ -7011,7 +9439,9 @@ "type": ["null", "object"], "properties": {} }, - "dynamic_last4": { "type": ["null", "string"] }, + "dynamic_last4": { + "type": ["null", "string"] + }, "google_pay": { "description": "Details of the Google Pay wallet.", "type": ["null", "object"], @@ -7024,25 +9454,53 @@ "billing_address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "email": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, + "email": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, "shipping_address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } } } @@ -7052,7 +9510,9 @@ "type": ["null", "object"], "properties": {} }, - "type": { "type": ["null", "string"] }, + "type": { + "type": ["null", "string"] + }, "visa_checkout": { "description": "Details of the Visa Checkout wallet.", "type": ["null", "object"], @@ -7060,25 +9520,53 @@ "billing_address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "email": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, + "email": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, "shipping_address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } } } @@ -7089,17 +9577,39 @@ "description": "Details of the card present during payment.", "type": ["null", "object"], "properties": { - "brand": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "emv_auth_data": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "exp_year": { "type": ["null", "integer"] }, - "fingerprint": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, - "generated_card": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "network": { "type": ["null", "string"] }, - "read_method": { "type": ["null", "string"] }, + "brand": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "emv_auth_data": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, + "generated_card": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + }, + "network": { + "type": ["null", "string"] + }, + "read_method": { + "type": ["null", "string"] + }, "receipt": { "description": "Receipt information related to the card payment.", "type": ["null", "object"], @@ -7110,14 +9620,18 @@ "application_preferred_name": { "type": ["null", "string"] }, - "authorization_code": { "type": ["null", "string"] }, + "authorization_code": { + "type": ["null", "string"] + }, "authorization_response_code": { "type": ["null", "string"] }, "cardholder_verification_method": { "type": ["null", "string"] }, - "dedicated_file_name": { "type": ["null", "string"] }, + "dedicated_file_name": { + "type": ["null", "string"] + }, "terminal_verification_results": { "type": ["null", "string"] }, @@ -7132,27 +9646,45 @@ "description": "Details of the EPS payment method.", "type": ["null", "object"], "properties": { - "verified_name": { "type": ["null", "string"] } + "verified_name": { + "type": ["null", "string"] + } } }, "giropay": { "description": "Details of the Giropay payment method.", "type": ["null", "object"], "properties": { - "bank_code": { "type": ["null", "string"] }, - "bank_name": { "type": ["null", "string"] }, - "bic": { "type": ["null", "string"] }, - "verified_name": { "type": ["null", "string"] } + "bank_code": { + "type": ["null", "string"] + }, + "bank_name": { + "type": ["null", "string"] + }, + "bic": { + "type": ["null", "string"] + }, + "verified_name": { + "type": ["null", "string"] + } } }, "ideal": { "description": "Details of the iDeal payment method.", "type": ["null", "object"], "properties": { - "bank": { "type": ["null", "string"] }, - "bic": { "type": ["null", "string"] }, - "iban_last4": { "type": ["null", "string"] }, - "verified_name": { "type": ["null", "string"] } + "bank": { + "type": ["null", "string"] + }, + "bic": { + "type": ["null", "string"] + }, + "iban_last4": { + "type": ["null", "string"] + }, + "verified_name": { + "type": ["null", "string"] + } } }, "klarna": { @@ -7164,40 +9696,72 @@ "description": "Details of the Multibanco payment method.", "type": ["null", "object"], "properties": { - "entity": { "type": ["null", "string"] }, - "reference": { "type": ["null", "string"] } + "entity": { + "type": ["null", "string"] + }, + "reference": { + "type": ["null", "string"] + } } }, "p24": { "description": "Details of the Przelewy24 payment method.", "type": ["null", "object"], "properties": { - "reference": { "type": ["null", "string"] }, - "verified_name": { "type": ["null", "string"] } + "reference": { + "type": ["null", "string"] + }, + "verified_name": { + "type": ["null", "string"] + } } }, "sepa_debit": { "description": "Details of the SEPA Direct Debit payment method.", "type": ["null", "object"], "properties": { - "bank_code": { "type": ["null", "string"] }, - "branch_code": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "mandate": { "type": ["null", "string"] } + "bank_code": { + "type": ["null", "string"] + }, + "branch_code": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + }, + "mandate": { + "type": ["null", "string"] + } } }, "sofort": { "description": "Details of the SOFORT payment method.", "type": ["null", "object"], "properties": { - "bank_code": { "type": ["null", "string"] }, - "bank_name": { "type": ["null", "string"] }, - "bic": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "iban_last4": { "type": ["null", "string"] }, - "verified_name": { "type": ["null", "string"] } + "bank_code": { + "type": ["null", "string"] + }, + "bank_name": { + "type": ["null", "string"] + }, + "bic": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "iban_last4": { + "type": ["null", "string"] + }, + "verified_name": { + "type": ["null", "string"] + } } }, "stripe_account": { @@ -7205,7 +9769,9 @@ "type": ["null", "object"], "properties": {} }, - "type": { "type": ["null", "string"] }, + "type": { + "type": ["null", "string"] + }, "wechat": { "description": "Details of the WeChat Pay payment method.", "type": ["null", "object"], @@ -7216,24 +9782,56 @@ "type": ["null", "object"], "properties": {} }, - "address_state": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "address_line1_check": { "type": ["null", "string"] }, - "address_line1": { "type": ["null", "string"] }, - "tokenization_method": { "type": ["null", "string"] }, - "address_country": { "type": ["null", "string"] }, - "address_city": { "type": ["null", "string"] }, - "address_line2": { "type": ["null", "string"] }, - "customer": { "type": ["null", "string"] }, - "dynamic_last4": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "address_zip": { "type": ["null", "string"] }, - "address_zip_check": { "type": ["null", "string"] }, - "cvc_check": { "type": ["null", "string"] } + "address_state": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "address_line1_check": { + "type": ["null", "string"] + }, + "address_line1": { + "type": ["null", "string"] + }, + "tokenization_method": { + "type": ["null", "string"] + }, + "address_country": { + "type": ["null", "string"] + }, + "address_city": { + "type": ["null", "string"] + }, + "address_line2": { + "type": ["null", "string"] + }, + "customer": { + "type": ["null", "string"] + }, + "dynamic_last4": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "address_zip": { + "type": ["null", "string"] + }, + "address_zip_check": { + "type": ["null", "string"] + }, + "cvc_check": { + "type": ["null", "string"] + } } }, - "type": { "type": ["null", "string"] } + "type": { + "type": ["null", "string"] + } } }, "balance_transaction": { @@ -7272,8 +9870,12 @@ "description": "Details of the transfer associated with the charge.", "type": ["null", "object"], "properties": { - "amount": { "type": ["null", "integer"] }, - "destination": { "type": ["null", "string"] } + "amount": { + "type": ["null", "integer"] + }, + "destination": { + "type": ["null", "string"] + } } }, "billing_details": { @@ -7284,12 +9886,24 @@ "description": "The address details of the customer.", "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, "email": { @@ -7321,7 +9935,9 @@ "amount_updates": { "description": "Additional items related to changes in the amount.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "payment_method": { "description": "The ID of the payment method used for the charge.", @@ -7430,7 +10046,10 @@ "json_schema": { "type": ["null", "object"], "properties": { - "id": { "description": "The ID of the dispute.", "type": ["string"] }, + "id": { + "description": "The ID of the dispute.", + "type": ["string"] + }, "object": { "description": "Type of object being returned.", "type": ["null", "string"] @@ -7473,43 +10092,105 @@ "description": "Evidence provided for the dispute.", "type": ["null", "string", "object"], "properties": { - "refund_policy": { "type": ["null", "string"] }, - "shipping_address": { "type": ["null", "string"] }, - "duplicate_charge_explanation": { "type": ["null", "string"] }, - "shipping_tracking_number": { "type": ["null", "string"] }, - "customer_signature": { "type": ["null", "string"] }, - "uncategorized_text": { "type": ["null", "string"] }, - "cancellation_policy_disclosure": { "type": ["null", "string"] }, - "refund_policy_disclosure": { "type": ["null", "string"] }, - "receipt": { "type": ["null", "string"] }, - "customer_name": { "type": ["null", "string"] }, - "refund_refusal_explanation": { "type": ["null", "string"] }, - "cancellation_rebuttal": { "type": ["null", "string"] }, - "product_description": { "type": ["null", "string"] }, - "shipping_date": { "type": ["null", "string"] }, - "customer_email_address": { "type": ["null", "string"] }, - "duplicate_charge_id": { "type": ["null", "string"] }, - "shipping_documentation": { "type": ["null", "string"] }, - "access_activity_log": { "type": ["null", "string"] }, - "customer_purchase_ip": { "type": ["null", "string"] }, - "service_date": { "type": ["null", "string"] }, - "shipping_carrier": { "type": ["null", "string"] }, - "service_documentation": { "type": ["null", "string"] }, - "duplicate_charge_documentation": { "type": ["null", "string"] }, - "cancellation_policy": { "type": ["null", "string"] }, - "customer_communication": { "type": ["null", "string"] }, - "uncategorized_file": { "type": ["null", "string"] }, - "billing_address": { "type": ["null", "string"] } + "refund_policy": { + "type": ["null", "string"] + }, + "shipping_address": { + "type": ["null", "string"] + }, + "duplicate_charge_explanation": { + "type": ["null", "string"] + }, + "shipping_tracking_number": { + "type": ["null", "string"] + }, + "customer_signature": { + "type": ["null", "string"] + }, + "uncategorized_text": { + "type": ["null", "string"] + }, + "cancellation_policy_disclosure": { + "type": ["null", "string"] + }, + "refund_policy_disclosure": { + "type": ["null", "string"] + }, + "receipt": { + "type": ["null", "string"] + }, + "customer_name": { + "type": ["null", "string"] + }, + "refund_refusal_explanation": { + "type": ["null", "string"] + }, + "cancellation_rebuttal": { + "type": ["null", "string"] + }, + "product_description": { + "type": ["null", "string"] + }, + "shipping_date": { + "type": ["null", "string"] + }, + "customer_email_address": { + "type": ["null", "string"] + }, + "duplicate_charge_id": { + "type": ["null", "string"] + }, + "shipping_documentation": { + "type": ["null", "string"] + }, + "access_activity_log": { + "type": ["null", "string"] + }, + "customer_purchase_ip": { + "type": ["null", "string"] + }, + "service_date": { + "type": ["null", "string"] + }, + "shipping_carrier": { + "type": ["null", "string"] + }, + "service_documentation": { + "type": ["null", "string"] + }, + "duplicate_charge_documentation": { + "type": ["null", "string"] + }, + "cancellation_policy": { + "type": ["null", "string"] + }, + "customer_communication": { + "type": ["null", "string"] + }, + "uncategorized_file": { + "type": ["null", "string"] + }, + "billing_address": { + "type": ["null", "string"] + } } }, "evidence_details": { "description": "Details about the evidence provided for the dispute.", "type": ["null", "object"], "properties": { - "due_by": { "type": ["null", "number"] }, - "has_evidence": { "type": ["null", "boolean"] }, - "past_due": { "type": ["null", "boolean"] }, - "submission_count": { "type": ["null", "integer"] } + "due_by": { + "type": ["null", "number"] + }, + "has_evidence": { + "type": ["null", "boolean"] + }, + "past_due": { + "type": ["null", "boolean"] + }, + "submission_count": { + "type": ["null", "integer"] + } } }, "is_charge_refundable": { @@ -7549,8 +10230,12 @@ "description": "Details of the card used for payment.", "type": ["null", "object"], "properties": { - "brand": { "type": ["null", "string"] }, - "network_reason_code": { "type": ["null", "string"] } + "brand": { + "type": ["null", "string"] + }, + "network_reason_code": { + "type": ["null", "string"] + } } }, "type": { @@ -7727,8 +10412,12 @@ "type": ["null", "object"], "additionalProperties": true, "properties": { - "type": { "type": ["null", "string"] }, - "value": { "type": ["null", "string"] } + "type": { + "type": ["null", "string"] + }, + "value": { + "type": ["null", "string"] + } } } }, @@ -7799,9 +10488,15 @@ "type": ["null", "object"], "additionalProperties": true, "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "checkout_session": { "type": ["null", "string"] }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "checkout_session": { + "type": ["null", "string"] + }, "coupon": { "type": ["null", "object"], "properties": { @@ -7810,20 +10505,48 @@ "additionalProperties": true, "properties": {} }, - "valid": { "type": ["null", "boolean"] }, - "livemode": { "type": ["null", "boolean"] }, - "amount_off": { "type": ["null", "integer"] }, - "redeem_by": { "type": ["null", "integer"] }, - "duration_in_months": { "type": ["null", "integer"] }, - "max_redemptions": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "times_redeemed": { "type": ["null", "integer"] }, - "id": { "type": ["null", "string"] }, - "duration": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "percent_off": { "type": ["null", "number"] }, - "created": { "type": ["null", "integer"] } + "valid": { + "type": ["null", "boolean"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "amount_off": { + "type": ["null", "integer"] + }, + "redeem_by": { + "type": ["null", "integer"] + }, + "duration_in_months": { + "type": ["null", "integer"] + }, + "max_redemptions": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "times_redeemed": { + "type": ["null", "integer"] + }, + "id": { + "type": ["null", "string"] + }, + "duration": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "percent_off": { + "type": ["null", "number"] + }, + "created": { + "type": ["null", "integer"] + } } } } @@ -7833,36 +10556,87 @@ "description": "Details about any discounts applied to the invoice", "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "checkout_session": { "type": ["null", "string"] }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "checkout_session": { + "type": ["null", "string"] + }, "coupon": { "type": ["null", "object"], "properties": { - "metadata": { "type": ["null", "object"], "properties": {} }, - "valid": { "type": ["null", "boolean"] }, - "livemode": { "type": ["null", "boolean"] }, - "amount_off": { "type": ["null", "integer"] }, - "redeem_by": { "type": ["null", "integer"] }, - "duration_in_months": { "type": ["null", "integer"] }, - "max_redemptions": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "times_redeemed": { "type": ["null", "integer"] }, - "id": { "type": ["null", "string"] }, - "duration": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "percent_off": { "type": ["null", "number"] }, - "created": { "type": ["null", "integer"] } - } - }, - "customer": { "type": ["null", "string"] }, - "end": { "type": ["null", "integer"] }, - "invoice": { "type": ["null", "string"] }, - "invoice_item": { "type": ["null", "string"] }, - "promotion_code": { "type": ["null", "string"] }, - "start": { "type": ["null", "integer"] }, - "subscription": { "type": ["null", "string"] } + "metadata": { + "type": ["null", "object"], + "properties": {} + }, + "valid": { + "type": ["null", "boolean"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "amount_off": { + "type": ["null", "integer"] + }, + "redeem_by": { + "type": ["null", "integer"] + }, + "duration_in_months": { + "type": ["null", "integer"] + }, + "max_redemptions": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "times_redeemed": { + "type": ["null", "integer"] + }, + "id": { + "type": ["null", "string"] + }, + "duration": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "percent_off": { + "type": ["null", "number"] + }, + "created": { + "type": ["null", "integer"] + } + } + }, + "customer": { + "type": ["null", "string"] + }, + "end": { + "type": ["null", "integer"] + }, + "invoice": { + "type": ["null", "string"] + }, + "invoice_item": { + "type": ["null", "string"] + }, + "promotion_code": { + "type": ["null", "string"] + }, + "start": { + "type": ["null", "integer"] + }, + "subscription": { + "type": ["null", "string"] + } } }, "number": { @@ -7948,7 +10722,11 @@ "subscription_details": { "description": "Details about the subscription associated with the invoice", "type": ["null", "object"], - "properties": { "metadata": { "type": ["null", "object"] } } + "properties": { + "metadata": { + "type": ["null", "object"] + } + } }, "status": { "description": "The current status of the invoice", @@ -7958,10 +10736,18 @@ "description": "Timestamps for status transitions of the invoice", "type": "object", "properties": { - "finalized_at": { "type": ["null", "integer"] }, - "marked_uncollectible_at": { "type": ["null", "integer"] }, - "paid_at": { "type": ["null", "integer"] }, - "voided_at": { "type": ["null", "integer"] } + "finalized_at": { + "type": ["null", "integer"] + }, + "marked_uncollectible_at": { + "type": ["null", "integer"] + }, + "paid_at": { + "type": ["null", "integer"] + }, + "voided_at": { + "type": ["null", "integer"] + } } }, "post_payment_credit_notes_amount": { @@ -7978,8 +10764,12 @@ "items": { "type": ["null", "object"], "properties": { - "amount": { "type": ["null", "integer"] }, - "discount": { "type": ["null", "string"] } + "amount": { + "type": ["null", "integer"] + }, + "discount": { + "type": ["null", "string"] + } } } }, @@ -7991,13 +10781,23 @@ "description": "The cost details associated with shipping", "type": ["null", "object"], "properties": { - "amount_subtotal": { "type": ["null", "integer"] }, - "amount_tax": { "type": ["null", "integer"] }, - "amount_total": { "type": ["null", "integer"] }, - "shipping_rate": { "type": ["null", "string"] }, + "amount_subtotal": { + "type": ["null", "integer"] + }, + "amount_tax": { + "type": ["null", "integer"] + }, + "amount_total": { + "type": ["null", "integer"] + }, + "shipping_rate": { + "type": ["null", "string"] + }, "taxes": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, @@ -8007,8 +10807,12 @@ "items": { "type": ["null", "object"], "properties": { - "name": { "type": ["null", "string"] }, - "value": { "type": ["null", "string"] } + "name": { + "type": ["null", "string"] + }, + "value": { + "type": ["null", "string"] + } } } }, @@ -8016,8 +10820,12 @@ "description": "Details about transfer of funds related to the invoice", "type": ["null", "object"], "properties": { - "amount": { "type": ["null", "integer"] }, - "destination": { "type": ["null", "string"] } + "amount": { + "type": ["null", "integer"] + }, + "destination": { + "type": ["null", "string"] + } } }, "application_fee_amount": { @@ -8032,16 +10840,32 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "name": { "type": ["null", "string"] }, - "phone": { "type": ["null", "string"] } + "name": { + "type": ["null", "string"] + }, + "phone": { + "type": ["null", "string"] + } } }, "application": { @@ -8056,8 +10880,12 @@ "description": "Details about the previous invoice", "type": ["null", "object"], "properties": { - "actions": { "type": ["null", "string"] }, - "invoice": { "type": ["null", "string"] } + "actions": { + "type": ["null", "string"] + }, + "invoice": { + "type": ["null", "string"] + } } }, "customer_tax_exempt": { @@ -8070,30 +10898,68 @@ "items": { "type": ["null", "object"], "properties": { - "amount": { "type": ["null", "integer"] }, - "inclusive": { "type": ["null", "boolean"] }, + "amount": { + "type": ["null", "integer"] + }, + "inclusive": { + "type": ["null", "boolean"] + }, "tax_rate": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "active": { "type": ["null", "boolean"] }, - "country": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "description": { "type": ["null", "string"] }, - "display_name": { "type": ["null", "string"] }, - "effective_percentage": { "type": ["null", "number"] }, - "inclusive": { "type": ["null", "boolean"] }, - "jurisdiction": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"] }, - "percentage": { "type": ["null", "number"] }, - "state": { "type": ["null", "string"] }, - "tax_type": { "type": ["null", "string"] } + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "active": { + "type": ["null", "boolean"] + }, + "country": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "description": { + "type": ["null", "string"] + }, + "display_name": { + "type": ["null", "string"] + }, + "effective_percentage": { + "type": ["null", "number"] + }, + "inclusive": { + "type": ["null", "boolean"] + }, + "jurisdiction": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"] + }, + "percentage": { + "type": ["null", "number"] + }, + "state": { + "type": ["null", "string"] + }, + "tax_type": { + "type": ["null", "string"] + } } }, - "taxability_reason": { "type": ["null", "string"] }, - "taxable_amount": { "type": ["null", "integer"] } + "taxability_reason": { + "type": ["null", "string"] + }, + "taxable_amount": { + "type": ["null", "integer"] + } } } }, @@ -8109,19 +10975,29 @@ "description": "Details about automatic tax calculation", "type": ["null", "object"], "properties": { - "enabled": { "type": ["null", "boolean"] }, - "status": { "type": ["null", "string"] } + "enabled": { + "type": ["null", "boolean"] + }, + "status": { + "type": ["null", "string"] + } } }, "payment_settings": { "description": "Settings related to payment on the invoice", "type": ["null", "object"], "properties": { - "default_mandate": { "type": ["null", "string"] }, - "payment_method_options": { "type": ["null", "object"] }, + "default_mandate": { + "type": ["null", "string"] + }, + "payment_method_options": { + "type": ["null", "object"] + }, "payment_method_types": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, @@ -8144,16 +11020,32 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "name": { "type": ["null", "string"] }, - "phone": { "type": ["null", "string"] } + "name": { + "type": ["null", "string"] + }, + "phone": { + "type": ["null", "string"] + } } }, "collection_method": { @@ -8169,21 +11061,51 @@ "items": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "active": { "type": ["null", "boolean"] }, - "country": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "description": { "type": ["null", "string"] }, - "display_name": { "type": ["null", "string"] }, - "effective_percentage": { "type": ["null", "number"] }, - "inclusive": { "type": ["null", "boolean"] }, - "jurisdiction": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"] }, - "percentage": { "type": ["null", "number"] }, - "state": { "type": ["null", "string"] }, - "tax_type": { "type": ["null", "string"] } + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "active": { + "type": ["null", "boolean"] + }, + "country": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "description": { + "type": ["null", "string"] + }, + "display_name": { + "type": ["null", "string"] + }, + "effective_percentage": { + "type": ["null", "number"] + }, + "inclusive": { + "type": ["null", "boolean"] + }, + "jurisdiction": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"] + }, + "percentage": { + "type": ["null", "number"] + }, + "state": { + "type": ["null", "string"] + }, + "tax_type": { + "type": ["null", "string"] + } } } }, @@ -8199,18 +11121,34 @@ "description": "Details about the last finalization error associated with the invoice", "type": ["null", "object"], "properties": { - "type": { "type": ["null", "string"] }, - "code": { "type": ["null", "string"] }, - "doc_url": { "type": ["null", "string"] }, - "message": { "type": ["null", "string"] }, - "param": { "type": ["null", "string"] }, - "payment_method_type": { "type": ["null", "string"] } + "type": { + "type": ["null", "string"] + }, + "code": { + "type": ["null", "string"] + }, + "doc_url": { + "type": ["null", "string"] + }, + "message": { + "type": ["null", "string"] + }, + "param": { + "type": ["null", "string"] + }, + "payment_method_type": { + "type": ["null", "string"] + } } }, "issuer": { "description": "Details about the issuer of the invoice", "type": ["null", "object"], - "properties": { "type": { "type": ["null", "string"] } } + "properties": { + "type": { + "type": ["null", "string"] + } + } }, "latest_revision": { "description": "The latest revision number of the invoice", @@ -8220,7 +11158,9 @@ "description": "Rendering options for the invoice", "type": ["null", "object"], "properties": { - "amount_tax_display": { "type": ["null", "string"] } + "amount_tax_display": { + "type": ["null", "string"] + } } }, "quote": { @@ -8242,7 +11182,9 @@ "account_tax_ids": { "description": "The tax IDs associated with the account", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "customer_email": { "description": "The email address of the customer", @@ -8252,12 +11194,24 @@ "description": "The address details of the customer", "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, "account_name": { @@ -8276,10 +11230,16 @@ "description": "Rendering details for the invoice", "type": ["object", "null"], "properties": { - "amount_tax_display": { "type": ["null", "string"] }, + "amount_tax_display": { + "type": ["null", "string"] + }, "pdf": { "type": ["null", "object"], - "properties": { "page_size": { "type": ["null", "string"] } } + "properties": { + "page_size": { + "type": ["null", "string"] + } + } } } } @@ -8498,51 +11458,105 @@ "price": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "active": { "type": ["null", "boolean"] }, - "billing_scheme": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "currency_options": { "type": ["null", "string"] }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "active": { + "type": ["null", "boolean"] + }, + "billing_scheme": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "currency_options": { + "type": ["null", "string"] + }, "custom_unit_amount": { "type": ["null", "object"], "properties": { - "maximum": { "type": ["null", "integer"] }, - "minimum": { "type": ["null", "integer"] }, - "preset": { "type": ["null", "integer"] } + "maximum": { + "type": ["null", "integer"] + }, + "minimum": { + "type": ["null", "integer"] + }, + "preset": { + "type": ["null", "integer"] + } } }, - "livemode": { "type": ["null", "boolean"] }, - "lookup_key": { "type": ["null", "string"] }, - "metadata": { "type": ["null", "object"] }, - "nickname": { "type": ["null", "string"] }, - "product": { "type": ["null", "string"] }, + "livemode": { + "type": ["null", "boolean"] + }, + "lookup_key": { + "type": ["null", "string"] + }, + "metadata": { + "type": ["null", "object"] + }, + "nickname": { + "type": ["null", "string"] + }, + "product": { + "type": ["null", "string"] + }, "recurring": { "type": ["null", "object"], "properties": { - "aggregate_usage": { "type": ["null", "string"] }, - "interval": { "type": ["null", "string"] }, - "interval_count": { "type": ["null", "integer"] }, - "usage_type": { "type": ["null", "string"] } + "aggregate_usage": { + "type": ["null", "string"] + }, + "interval": { + "type": ["null", "string"] + }, + "interval_count": { + "type": ["null", "integer"] + }, + "usage_type": { + "type": ["null", "string"] + } } }, - "tax_behavior": { "type": ["null", "string"] }, + "tax_behavior": { + "type": ["null", "string"] + }, "tiers": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } + }, + "tiers_mode": { + "type": ["null", "string"] }, - "tiers_mode": { "type": ["null", "string"] }, "transform_quantity": { "type": ["null", "object"], "properties": { - "divide_by": { "type": ["null", "integer"] }, - "round": { "type": ["null", "string"] } + "divide_by": { + "type": ["null", "integer"] + }, + "round": { + "type": ["null", "string"] + } } }, - "type": { "type": ["null", "string"] }, - "unit_amount": { "type": ["null", "integer"] }, - "unit_amount_decimal": { "type": ["null", "string"] } + "type": { + "type": ["null", "string"] + }, + "unit_amount": { + "type": ["null", "integer"] + }, + "unit_amount_decimal": { + "type": ["null", "string"] + } } }, "test_clock": { @@ -8562,21 +11576,51 @@ "items": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "active": { "type": ["null", "boolean"] }, - "country": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "description": { "type": ["null", "string"] }, - "display_name": { "type": ["null", "string"] }, - "effective_percentage": { "type": ["null", "number"] }, - "inclusive": { "type": ["null", "boolean"] }, - "jurisdiction": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"] }, - "percentage": { "type": ["null", "number"] }, - "state": { "type": ["null", "string"] }, - "tax_type": { "type": ["null", "string"] } + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "active": { + "type": ["null", "boolean"] + }, + "country": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "description": { + "type": ["null", "string"] + }, + "display_name": { + "type": ["null", "string"] + }, + "effective_percentage": { + "type": ["null", "number"] + }, + "inclusive": { + "type": ["null", "boolean"] + }, + "jurisdiction": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"] + }, + "percentage": { + "type": ["null", "number"] + }, + "state": { + "type": ["null", "string"] + }, + "tax_type": { + "type": ["null", "string"] + } } } }, @@ -8808,11 +11852,21 @@ "items": { "type": ["null", "string", "object"], "properties": { - "flat_amount": { "type": ["null", "integer"] }, - "flat_amount_decimal": { "type": ["null", "string"] }, - "unit_amount": { "type": ["null", "integer"] }, - "unit_amount_decimal": { "type": ["null", "string"] }, - "up_to": { "type": ["null", "integer"] } + "flat_amount": { + "type": ["null", "integer"] + }, + "flat_amount_decimal": { + "type": ["null", "string"] + }, + "unit_amount": { + "type": ["null", "integer"] + }, + "unit_amount_decimal": { + "type": ["null", "string"] + }, + "up_to": { + "type": ["null", "integer"] + } } } }, @@ -9697,7 +12751,9 @@ "payment_method_types": { "description": "Supported payment method types.", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "save_default_payment_method": { "description": "Indicates if the default payment method should be saved.", @@ -9740,21 +12796,51 @@ "items": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "active": { "type": ["null", "boolean"] }, - "country": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "description": { "type": ["null", "string"] }, - "display_name": { "type": ["null", "string"] }, - "effective_percentage": { "type": ["null", "number"] }, - "inclusive": { "type": ["null", "boolean"] }, - "jurisdiction": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"] }, - "percentage": { "type": ["null", "number"] }, - "state": { "type": ["null", "string"] }, - "tax_type": { "type": ["null", "string"] } + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "active": { + "type": ["null", "boolean"] + }, + "country": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "description": { + "type": ["null", "string"] + }, + "display_name": { + "type": ["null", "string"] + }, + "effective_percentage": { + "type": ["null", "number"] + }, + "inclusive": { + "type": ["null", "boolean"] + }, + "jurisdiction": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"] + }, + "percentage": { + "type": ["null", "number"] + }, + "state": { + "type": ["null", "string"] + }, + "tax_type": { + "type": ["null", "string"] + } } } }, @@ -9841,51 +12927,105 @@ "price": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "active": { "type": ["null", "boolean"] }, - "billing_scheme": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "currency_options": { "type": ["null", "string"] }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "active": { + "type": ["null", "boolean"] + }, + "billing_scheme": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "currency_options": { + "type": ["null", "string"] + }, "custom_unit_amount": { "type": ["null", "object"], "properties": { - "maximum": { "type": ["null", "integer"] }, - "minimum": { "type": ["null", "integer"] }, - "preset": { "type": ["null", "integer"] } + "maximum": { + "type": ["null", "integer"] + }, + "minimum": { + "type": ["null", "integer"] + }, + "preset": { + "type": ["null", "integer"] + } } }, - "livemode": { "type": ["null", "boolean"] }, - "lookup_key": { "type": ["null", "string"] }, - "metadata": { "type": ["null", "object"] }, - "nickname": { "type": ["null", "string"] }, - "product": { "type": ["null", "string"] }, + "livemode": { + "type": ["null", "boolean"] + }, + "lookup_key": { + "type": ["null", "string"] + }, + "metadata": { + "type": ["null", "object"] + }, + "nickname": { + "type": ["null", "string"] + }, + "product": { + "type": ["null", "string"] + }, "recurring": { "type": ["null", "object"], "properties": { - "aggregate_usage": { "type": ["null", "string"] }, - "interval": { "type": ["null", "string"] }, - "interval_count": { "type": ["null", "integer"] }, - "usage_type": { "type": ["null", "string"] } + "aggregate_usage": { + "type": ["null", "string"] + }, + "interval": { + "type": ["null", "string"] + }, + "interval_count": { + "type": ["null", "integer"] + }, + "usage_type": { + "type": ["null", "string"] + } } }, - "tax_behavior": { "type": ["null", "string"] }, + "tax_behavior": { + "type": ["null", "string"] + }, "tiers": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } + }, + "tiers_mode": { + "type": ["null", "string"] }, - "tiers_mode": { "type": ["null", "string"] }, "transform_quantity": { "type": ["null", "object"], "properties": { - "divide_by": { "type": ["null", "integer"] }, - "round": { "type": ["null", "string"] } + "divide_by": { + "type": ["null", "integer"] + }, + "round": { + "type": ["null", "string"] + } } }, - "type": { "type": ["null", "string"] }, - "unit_amount": { "type": ["null", "integer"] }, - "unit_amount_decimal": { "type": ["null", "string"] } + "type": { + "type": ["null", "string"] + }, + "unit_amount": { + "type": ["null", "integer"] + }, + "unit_amount_decimal": { + "type": ["null", "string"] + } } }, "quantity": { @@ -9901,23 +13041,51 @@ "items": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "active": { "type": ["null", "boolean"] }, - "country": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "description": { "type": ["null", "string"] }, - "display_name": { "type": ["null", "string"] }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "active": { + "type": ["null", "boolean"] + }, + "country": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "description": { + "type": ["null", "string"] + }, + "display_name": { + "type": ["null", "string"] + }, "effective_percentage": { "type": ["null", "number"] }, - "inclusive": { "type": ["null", "boolean"] }, - "jurisdiction": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"] }, - "percentage": { "type": ["null", "number"] }, - "state": { "type": ["null", "string"] }, - "tax_type": { "type": ["null", "string"] } + "inclusive": { + "type": ["null", "boolean"] + }, + "jurisdiction": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"] + }, + "percentage": { + "type": ["null", "number"] + }, + "state": { + "type": ["null", "string"] + }, + "tax_type": { + "type": ["null", "string"] + } } } } @@ -10135,23 +13303,51 @@ "items": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "active": { "type": ["null", "boolean"] }, - "country": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "description": { "type": ["null", "string"] }, - "display_name": { "type": ["null", "string"] }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "active": { + "type": ["null", "boolean"] + }, + "country": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "description": { + "type": ["null", "string"] + }, + "display_name": { + "type": ["null", "string"] + }, "effective_percentage": { "type": ["null", "number"] }, - "inclusive": { "type": ["null", "boolean"] }, - "jurisdiction": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"] }, - "percentage": { "type": ["null", "number"] }, - "state": { "type": ["null", "string"] }, - "tax_type": { "type": ["null", "string"] } + "inclusive": { + "type": ["null", "boolean"] + }, + "jurisdiction": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"] + }, + "percentage": { + "type": ["null", "number"] + }, + "state": { + "type": ["null", "string"] + }, + "tax_type": { + "type": ["null", "string"] + } } } } @@ -10191,21 +13387,51 @@ "items": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "active": { "type": ["null", "boolean"] }, - "country": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "description": { "type": ["null", "string"] }, - "display_name": { "type": ["null", "string"] }, - "effective_percentage": { "type": ["null", "number"] }, - "inclusive": { "type": ["null", "boolean"] }, - "jurisdiction": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"] }, - "percentage": { "type": ["null", "number"] }, - "state": { "type": ["null", "string"] }, - "tax_type": { "type": ["null", "string"] } + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "active": { + "type": ["null", "boolean"] + }, + "country": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "description": { + "type": ["null", "string"] + }, + "display_name": { + "type": ["null", "string"] + }, + "effective_percentage": { + "type": ["null", "number"] + }, + "inclusive": { + "type": ["null", "boolean"] + }, + "jurisdiction": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"] + }, + "percentage": { + "type": ["null", "number"] + }, + "state": { + "type": ["null", "string"] + }, + "tax_type": { + "type": ["null", "string"] + } } } }, @@ -10459,147 +13685,295 @@ "json_schema": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "amount": { "type": ["null", "integer"] }, - "amount_capturable": { "type": ["null", "integer"] }, - "amount_received": { "type": ["null", "integer"] }, - "application": { "type": ["null", "string"] }, - "application_fee_amount": { "type": ["null", "integer"] }, - "canceled_at": { "type": ["null", "integer"] }, - "cancellation_reason": { "type": ["null", "string"] }, - "capture_method": { "type": ["null", "string"] }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "amount": { + "type": ["null", "integer"] + }, + "amount_capturable": { + "type": ["null", "integer"] + }, + "amount_received": { + "type": ["null", "integer"] + }, + "application": { + "type": ["null", "string"] + }, + "application_fee_amount": { + "type": ["null", "integer"] + }, + "canceled_at": { + "type": ["null", "integer"] + }, + "cancellation_reason": { + "type": ["null", "string"] + }, + "capture_method": { + "type": ["null", "string"] + }, "charges": { "type": ["null", "object"], "properties": { - "object": { "type": ["null", "string"] }, - "data": { "type": ["null", "array"] }, - "has_more": { "type": ["null", "boolean"] }, - "total_count": { "type": ["null", "integer"] }, - "url": { "type": ["null", "string"] } + "object": { + "type": ["null", "string"] + }, + "data": { + "type": ["null", "array"] + }, + "has_more": { + "type": ["null", "boolean"] + }, + "total_count": { + "type": ["null", "integer"] + }, + "url": { + "type": ["null", "string"] + } } }, - "client_secret": { "type": ["null", "string"] }, - "confirmation_method": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "updated": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "customer": { "type": ["null", "string"] }, - "description": { "type": ["null", "string"] }, - "invoice": { "type": ["null", "string"] }, + "client_secret": { + "type": ["null", "string"] + }, + "confirmation_method": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "updated": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "customer": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, + "invoice": { + "type": ["null", "string"] + }, "last_payment_error": { "type": ["null", "object"], "properties": { - "charge": { "type": ["null", "string"] }, - "code": { "type": ["null", "string"] }, - "decline_code": { "type": ["null", "string"] }, - "doc_url": { "type": ["null", "string"] }, - "message": { "type": ["null", "string"] }, - "param": { "type": ["null", "string"] }, + "charge": { + "type": ["null", "string"] + }, + "code": { + "type": ["null", "string"] + }, + "decline_code": { + "type": ["null", "string"] + }, + "doc_url": { + "type": ["null", "string"] + }, + "message": { + "type": ["null", "string"] + }, + "param": { + "type": ["null", "string"] + }, "payment_method": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, "acss_debit": { "type": ["null", "object"], "properties": { - "bank_name": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "institution_number": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "transit_number": { "type": ["null", "string"] } + "bank_name": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "institution_number": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + }, + "transit_number": { + "type": ["null", "string"] + } } }, - "afterpay_clearpay": { "type": ["null", "string"] }, - "alipay": { "type": ["null", "string"] }, + "afterpay_clearpay": { + "type": ["null", "string"] + }, + "alipay": { + "type": ["null", "string"] + }, "au_becs_debit": { "type": ["null", "object"], "properties": { - "bsb_number": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] } + "bsb_number": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + } } }, "bacs_debit": { "type": ["null", "object"], "properties": { - "fingerprint": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "sort_code": { "type": ["null", "string"] } + "fingerprint": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + }, + "sort_code": { + "type": ["null", "string"] + } } }, - "bancontact": { "type": ["null", "string"] }, + "bancontact": { + "type": ["null", "string"] + }, "billing_details": { "type": ["null", "object"], "properties": { "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "email": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "phone": { "type": ["null", "string"] } + "email": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "phone": { + "type": ["null", "string"] + } } }, "boleto": { "type": ["null", "object"], - "properties": { "tax_id": { "type": ["null", "string"] } } + "properties": { + "tax_id": { + "type": ["null", "string"] + } + } }, "card": { "type": ["null", "object"], "properties": { - "brand": { "type": ["null", "string"] }, + "brand": { + "type": ["null", "string"] + }, "checks": { "type": ["null", "object"], "properties": { - "address_line1_check": { "type": ["null", "string"] }, + "address_line1_check": { + "type": ["null", "string"] + }, "address_postal_code_check": { "type": ["null", "string"] }, - "cvc_check": { "type": ["null", "string"] } + "cvc_check": { + "type": ["null", "string"] + } } }, - "country": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "exp_year": { "type": ["null", "integer"] }, - "fingerprint": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, + "country": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, "generated_from": { "type": ["null", "object"], "properties": { - "charge": { "type": ["null", "string"] }, + "charge": { + "type": ["null", "string"] + }, "payment_method_details": { "type": ["null", "object"], "properties": { "card_present": { "type": ["null", "object"], "properties": { - "brand": { "type": ["null", "string"] }, + "brand": { + "type": ["null", "string"] + }, "cardholder_name": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, + "country": { + "type": ["null", "string"] + }, "emv_auth_data": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "exp_year": { "type": ["null", "integer"] }, - "fingerprint": { "type": ["null", "string"] }, - "funding": { "type": ["null", "string"] }, + "exp_month": { + "type": ["null", "integer"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "fingerprint": { + "type": ["null", "string"] + }, + "funding": { + "type": ["null", "string"] + }, "generated_card": { "type": ["null", "string"] }, - "lsat4": { "type": ["null", "string"] }, - "network": { "type": ["null", "string"] }, - "read_method": { "type": ["null", "string"] }, + "lsat4": { + "type": ["null", "string"] + }, + "network": { + "type": ["null", "string"] + }, + "read_method": { + "type": ["null", "string"] + }, "receipt": { "type": ["null", "object"], "properties": { @@ -10632,30 +14006,44 @@ } } }, - "type": { "type": ["null", "string"] } + "type": { + "type": ["null", "string"] + } } }, - "type": { "type": ["null", "string"] } + "type": { + "type": ["null", "string"] + } } }, - "setup_attempt": { "type": ["null", "string"] } + "setup_attempt": { + "type": ["null", "string"] + } } }, - "last4": { "type": ["null", "string"] }, + "last4": { + "type": ["null", "string"] + }, "networks": { "type": ["null", "object"], "properties": { "available": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, - "preferred": { "type": ["null", "string"] } + "preferred": { + "type": ["null", "string"] + } } }, "three_d_secure_usage": { "type": ["null", "object"], "properties": { - "supported": { "type": ["null", "boolean"] } + "supported": { + "type": ["null", "boolean"] + } } }, "wallet": { @@ -10664,65 +14052,131 @@ "amex_express_checkout": { "type": ["null", "string"] }, - "apple_pay": { "type": ["null", "string"] }, - "dynamic_last4": { "type": ["null", "string"] }, - "google_pay": { "type": ["null", "string"] }, + "apple_pay": { + "type": ["null", "string"] + }, + "dynamic_last4": { + "type": ["null", "string"] + }, + "google_pay": { + "type": ["null", "string"] + }, "masterpass": { "type": ["null", "object"], "properties": { "billing_address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "email": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, + "email": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, "shipping_address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } } } }, - "samsung_pay": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] }, + "samsung_pay": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, "visa_checkout": { "type": ["null", "object"], "properties": { "billing_address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "email": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, + "email": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, "shipping_address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } } } @@ -10735,101 +14189,195 @@ "type": ["null", "object"], "properties": {} }, - "created": { "type": ["null", "integer"] }, - "customer": { "type": ["null", "string"] }, + "created": { + "type": ["null", "integer"] + }, + "customer": { + "type": ["null", "string"] + }, "eps": { "type": ["null", "object"], - "properties": { "bank": { "type": ["null", "string"] } } + "properties": { + "bank": { + "type": ["null", "string"] + } + } }, "fpx": { "type": ["null", "object"], - "properties": { "bank": { "type": ["null", "string"] } } + "properties": { + "bank": { + "type": ["null", "string"] + } + } + }, + "giropay": { + "type": ["null", "object"], + "properties": {} + }, + "grabpay": { + "type": ["null", "object"], + "properties": {} }, - "giropay": { "type": ["null", "object"], "properties": {} }, - "grabpay": { "type": ["null", "object"], "properties": {} }, "ideal": { "type": ["null", "object"], - "properties": { "bank": { "type": ["null", "string"] } } + "properties": { + "bank": { + "type": ["null", "string"] + } + } }, "interac_present": { "type": ["null", "object"], "properties": {} }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"], "properties": {} }, - "oxxo": { "type": ["null", "object"], "properties": {} }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"], + "properties": {} + }, + "oxxo": { + "type": ["null", "object"], + "properties": {} + }, "p24": { "type": ["null", "object"], - "properties": { "bank": { "type": ["null", "string"] } } + "properties": { + "bank": { + "type": ["null", "string"] + } + } }, "sepa_debit": { "type": ["null", "object"], "properties": { - "bank_code": { "type": ["null", "string"] }, - "branch_code": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "fingerprint": { "type": ["null", "string"] }, + "bank_code": { + "type": ["null", "string"] + }, + "branch_code": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "fingerprint": { + "type": ["null", "string"] + }, "generated_from": { "type": ["null", "object"], "properties": { - "charge": { "type": ["null", "string"] }, - "setup_attempt": { "type": ["null", "string"] } + "charge": { + "type": ["null", "string"] + }, + "setup_attempt": { + "type": ["null", "string"] + } } }, - "last4": { "type": ["null", "string"] } + "last4": { + "type": ["null", "string"] + } } }, "sofort": { "type": ["null", "object"], - "properties": { "country": { "type": ["null", "string"] } } + "properties": { + "country": { + "type": ["null", "string"] + } + } }, - "type": { "type": ["null", "string"] }, - "wechat_pay": { "type": ["null", "object"], "properties": {} } + "type": { + "type": ["null", "string"] + }, + "wechat_pay": { + "type": ["null", "object"], + "properties": {} + } } }, - "payment_method_type": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } + "payment_method_type": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } } }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"], "properties": {} }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"], + "properties": {} + }, "next_action": { "type": ["null", "object"], "properties": { "alipay_handle_redirect": { "type": ["null", "object"], "properties": { - "native_data": { "type": ["null", "string"] }, - "native_url": { "type": ["null", "string"] }, - "return_url": { "type": ["null", "string"] }, - "url": { "type": ["null", "string"] } + "native_data": { + "type": ["null", "string"] + }, + "native_url": { + "type": ["null", "string"] + }, + "return_url": { + "type": ["null", "string"] + }, + "url": { + "type": ["null", "string"] + } } }, "boleto_display_details": { "type": ["null", "object"], "properties": { - "expires_at": { "type": ["null", "integer"] }, - "hosted_voucher_url": { "type": ["null", "string"] }, - "number": { "type": ["null", "string"] }, - "pdf": { "type": ["null", "string"] } + "expires_at": { + "type": ["null", "integer"] + }, + "hosted_voucher_url": { + "type": ["null", "string"] + }, + "number": { + "type": ["null", "string"] + }, + "pdf": { + "type": ["null", "string"] + } } }, "oxxo_display_details": { "type": ["null", "object"], "properties": { - "expires_after": { "type": ["null", "integer"] }, - "hosted_voucher_url": { "type": ["null", "string"] }, - "number": { "type": ["null", "string"] } + "expires_after": { + "type": ["null", "integer"] + }, + "hosted_voucher_url": { + "type": ["null", "string"] + }, + "number": { + "type": ["null", "string"] + } } }, "redirect_to_url": { "type": ["null", "object"], "properties": { - "return_url": { "type": ["null", "string"] }, - "url": { "type": ["null", "string"] } + "return_url": { + "type": ["null", "string"] + }, + "url": { + "type": ["null", "string"] + } } }, - "type": { "type": ["null", "string"] }, + "type": { + "type": ["null", "string"] + }, "use_stripe_sdk": { "type": ["null", "object"], "properties": {} @@ -10837,103 +14385,189 @@ "verify_with_microdeposits": { "type": ["null", "object"], "properties": { - "arrival_date": { "type": ["null", "integer"] }, - "hosted_verification_url": { "type": ["null", "string"] } + "arrival_date": { + "type": ["null", "integer"] + }, + "hosted_verification_url": { + "type": ["null", "string"] + } } }, "wechat_pay_display_qr_code": { "type": ["null", "object"], "properties": { - "data": { "type": ["null", "string"] }, - "image_data_url": { "type": ["null", "string"] } + "data": { + "type": ["null", "string"] + }, + "image_data_url": { + "type": ["null", "string"] + } } }, "wechat_pay_redirect_to_android_app": { "type": ["null", "object"], "properties": { - "app_id": { "type": ["null", "string"] }, - "nonce_str": { "type": ["null", "string"] }, - "package": { "type": ["null", "string"] }, - "partner_id": { "type": ["null", "string"] }, - "prepay_id": { "type": ["null", "string"] }, - "sign": { "type": ["null", "string"] }, - "timestamp": { "type": ["null", "string"] } + "app_id": { + "type": ["null", "string"] + }, + "nonce_str": { + "type": ["null", "string"] + }, + "package": { + "type": ["null", "string"] + }, + "partner_id": { + "type": ["null", "string"] + }, + "prepay_id": { + "type": ["null", "string"] + }, + "sign": { + "type": ["null", "string"] + }, + "timestamp": { + "type": ["null", "string"] + } } }, "wechat_pay_redirect_to_ios_app": { "type": ["null", "object"], - "properties": { "native_url": { "type": ["null", "string"] } } + "properties": { + "native_url": { + "type": ["null", "string"] + } + } } } }, - "on_behalf_of": { "type": ["null", "string"] }, - "payment_method": { "type": ["null", "string"] }, + "on_behalf_of": { + "type": ["null", "string"] + }, + "payment_method": { + "type": ["null", "string"] + }, "payment_method_options": { "type": ["null", "object"], "properties": {} }, "payment_method_types": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } + }, + "receipt_email": { + "type": ["null", "string"] + }, + "review": { + "type": ["null", "string"] + }, + "setup_future_usage": { + "type": ["null", "string"] }, - "receipt_email": { "type": ["null", "string"] }, - "review": { "type": ["null", "string"] }, - "setup_future_usage": { "type": ["null", "string"] }, "shipping": { "type": ["null", "object"], "properties": { "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "carrier": { "type": ["null", "string"] }, - "name": { "type": ["null", "string"] }, - "phone": { "type": ["null", "string"] }, - "tracking_number": { "type": ["null", "string"] } + "carrier": { + "type": ["null", "string"] + }, + "name": { + "type": ["null", "string"] + }, + "phone": { + "type": ["null", "string"] + }, + "tracking_number": { + "type": ["null", "string"] + } } }, - "source": { "type": ["null", "string"] }, - "statement_description": { "type": ["null", "string"] }, - "statement_descriptor_suffix": { "type": ["null", "string"] }, - "status": { "type": ["null", "string"] }, + "source": { + "type": ["null", "string"] + }, + "statement_description": { + "type": ["null", "string"] + }, + "statement_descriptor_suffix": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, "transfer_data": { "type": ["null", "object"], "properties": { - "amount": { "type": ["null", "integer"] }, - "destination": { "type": ["null", "string"] } + "amount": { + "type": ["null", "integer"] + }, + "destination": { + "type": ["null", "string"] + } } }, - "transfer_group": { "type": ["null", "string"] }, - "latest_charge": { "type": ["null", "string"] }, - "statement_descriptor": { "type": ["null", "string"] }, + "transfer_group": { + "type": ["null", "string"] + }, + "latest_charge": { + "type": ["null", "string"] + }, + "statement_descriptor": { + "type": ["null", "string"] + }, "amount_details": { "type": ["null", "object"], "properties": { "tip": { "type": ["null", "object"], - "properties": { "amount": { "type": ["null", "integer"] } } + "properties": { + "amount": { + "type": ["null", "integer"] + } + } } } }, "processing": { "type": ["null", "object"], "properties": { - "type": { "type": ["null", "string"] }, + "type": { + "type": ["null", "string"] + }, "card": { "type": ["null", "object"], "properties": { "customer_notification": { "type": ["null", "object"], "properties": { - "approval_requested": { "type": ["null", "boolean"] }, - "completes_at": { "type": ["null", "integer"] } + "approval_requested": { + "type": ["null", "boolean"] + }, + "completes_at": { + "type": ["null", "integer"] + } } } } @@ -10943,15 +14577,23 @@ "automatic_payment_methods": { "type": ["null", "object"], "properties": { - "allow_redirects": { "type": ["null", "string"] }, - "enabled": { "type": ["null", "boolean"] } + "allow_redirects": { + "type": ["null", "string"] + }, + "enabled": { + "type": ["null", "boolean"] + } } }, "payment_method_configuration_details": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "parent": { "type": ["null", "string"] } + "id": { + "type": ["null", "string"] + }, + "parent": { + "type": ["null", "string"] + } } } } @@ -11128,53 +14770,104 @@ "json_schema": { "type": ["null", "object"], "properties": { - "id": { "type": ["string"] }, - "object": { "type": ["string"], "enum": ["setup_intent"] }, - "application": { "type": ["null", "string"] }, - "cancellation_reason": { "type": ["null", "string"] }, - "created": { "type": ["integer"] }, - "updated": { "type": ["null", "integer"] }, - "customer": { "type": ["null", "string"] }, - "description": { "type": ["null", "string"] }, + "id": { + "type": ["string"] + }, + "object": { + "type": ["string"], + "enum": ["setup_intent"] + }, + "application": { + "type": ["null", "string"] + }, + "cancellation_reason": { + "type": ["null", "string"] + }, + "created": { + "type": ["integer"] + }, + "updated": { + "type": ["null", "integer"] + }, + "customer": { + "type": ["null", "string"] + }, + "description": { + "type": ["null", "string"] + }, "flow_directions": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } - }, - "last_setup_error": { "type": ["null", "string"] }, - "latest_attempt": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "mandate": { "type": ["null", "string"] }, - "metadata": { "type": ["null", "object"] }, - "next_action": { "type": ["null", "string"] }, - "on_behalf_of": { "type": ["null", "string"] }, - "payment_method": { "type": ["null", "string"] }, + "items": { + "type": ["null", "string"] + } + }, + "last_setup_error": { + "type": ["null", "string"] + }, + "latest_attempt": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "mandate": { + "type": ["null", "string"] + }, + "metadata": { + "type": ["null", "object"] + }, + "next_action": { + "type": ["null", "string"] + }, + "on_behalf_of": { + "type": ["null", "string"] + }, + "payment_method": { + "type": ["null", "string"] + }, "payment_method_options": { "type": ["null", "object"], "additionalProperties": true }, "payment_method_types": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } + }, + "single_use_mandate": { + "type": ["null", "string"] + }, + "status": { + "type": ["string"] }, - "single_use_mandate": { "type": ["null", "string"] }, - "status": { "type": ["string"] }, "usage": { "type": ["string"], "enum": ["on_session", "off_session"] }, - "client_secret": { "type": ["null", "string"] }, + "client_secret": { + "type": ["null", "string"] + }, "automatic_payment_methods": { "type": ["null", "object"], "properties": { - "allow_redirects": { "type": ["null", "string"] }, - "enabled": { "type": ["null", "boolean"] } + "allow_redirects": { + "type": ["null", "string"] + }, + "enabled": { + "type": ["null", "boolean"] + } } }, "payment_method_configuration_details": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "parent": { "type": ["null", "string"] } + "id": { + "type": ["null", "string"] + }, + "parent": { + "type": ["null", "string"] + } } } } @@ -11190,8 +14883,12 @@ "json_schema": { "type": ["null", "object"], "properties": { - "brand": { "type": ["null", "string"] }, - "cancellation_reason": { "type": ["null", "string"] }, + "brand": { + "type": ["null", "string"] + }, + "cancellation_reason": { + "type": ["null", "string"] + }, "cardholder": { "type": ["null", "object"], "properties": { @@ -11201,63 +14898,115 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } } } }, "company": { "type": ["null", "object"], - "properties": { "tax_id_provided": { "type": "boolean" } } + "properties": { + "tax_id_provided": { + "type": "boolean" + } + } + }, + "created": { + "type": ["null", "integer"] + }, + "updated": { + "type": ["null", "integer"] + }, + "email": { + "type": ["null", "string"] + }, + "id": { + "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "updated": { "type": ["null", "integer"] }, - "email": { "type": ["null", "string"] }, - "id": { "type": ["null", "string"] }, "individual": { "type": ["null", "object"], "properties": { "dob": { "type": ["null", "object"], "properties": { - "day": { "type": ["null", "integer"] }, - "month": { "type": ["null", "integer"] }, - "year": { "type": ["null", "integer"] } + "day": { + "type": ["null", "integer"] + }, + "month": { + "type": ["null", "integer"] + }, + "year": { + "type": ["null", "integer"] + } } }, - "first_name": { "type": ["null", "string"] }, - "last_name": { "type": ["null", "string"] }, + "first_name": { + "type": ["null", "string"] + }, + "last_name": { + "type": ["null", "string"] + }, "verification": { "type": ["null", "object"], "properties": { "document": { "type": ["null", "object"], "properties": { - "back": { "type": ["null", "string"] }, - "front": { "type": ["null", "string"] } + "back": { + "type": ["null", "string"] + }, + "front": { + "type": ["null", "string"] + } } } } } } }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"] }, - "name": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "phone_number": { "type": ["null", "string"] }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"] + }, + "name": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "phone_number": { + "type": ["null", "string"] + }, "requirements": { "type": ["null", "object"], "properties": { - "disabled_reason": { "type": ["null", "string"] }, + "disabled_reason": { + "type": ["null", "string"] + }, "past_due": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, @@ -11266,42 +15015,78 @@ "properties": { "allowed_categories": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "blocked_categories": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "spending_limits": { "type": ["null", "array"], - "items": { "type": ["null", "object"] } + "items": { + "type": ["null", "object"] + } }, - "spending_limits_currency": { "type": ["null", "string"] } + "spending_limits_currency": { + "type": ["null", "string"] + } } }, - "status": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] }, + "status": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + }, "preferred_locales": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, - "created": { "type": ["null", "integer"] }, - "updated": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "cvc": { "type": ["null", "string"] }, - "exp_month": { "type": ["null", "integer"] }, - "exp_year": { "type": ["null", "integer"] }, - "id": { "type": ["null", "string"] }, - "last4": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, + "created": { + "type": ["null", "integer"] + }, + "updated": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "cvc": { + "type": ["null", "string"] + }, + "exp_month": { + "type": ["null", "integer"] + }, + "exp_year": { + "type": ["null", "integer"] + }, + "id": { + "type": ["null", "string"] + }, + "last4": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, "metadata": { "type": ["null", "object"], "additionalProperties": true }, - "number": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, + "number": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, "replaced_by": { "type": ["null", "object"], "additionalProperties": true @@ -11310,7 +15095,9 @@ "type": ["null", "object"], "additionalProperties": true }, - "replacement_reason": { "type": ["null", "string"] }, + "replacement_reason": { + "type": ["null", "string"] + }, "shipping": { "type": ["null", "object"], "additionalProperties": true, @@ -11318,22 +15105,50 @@ "address": { "type": ["null", "object"], "properties": { - "city": { "type": ["null", "string"] }, - "country": { "type": ["null", "string"] }, - "line1": { "type": ["null", "string"] }, - "line2": { "type": ["null", "string"] }, - "postal_code": { "type": ["null", "string"] }, - "state": { "type": ["null", "string"] } + "city": { + "type": ["null", "string"] + }, + "country": { + "type": ["null", "string"] + }, + "line1": { + "type": ["null", "string"] + }, + "line2": { + "type": ["null", "string"] + }, + "postal_code": { + "type": ["null", "string"] + }, + "state": { + "type": ["null", "string"] + } } }, - "carrier": { "type": ["null", "string"] }, - "eta": { "type": ["null", "integer"] }, - "name": { "type": ["null", "string"] }, - "service": { "type": ["null", "string"] }, - "status": { "type": ["null", "string"] }, - "tracking_number": { "type": ["null", "string"] }, - "tracking_url": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } + "carrier": { + "type": ["null", "string"] + }, + "eta": { + "type": ["null", "integer"] + }, + "name": { + "type": ["null", "string"] + }, + "service": { + "type": ["null", "string"] + }, + "status": { + "type": ["null", "string"] + }, + "tracking_number": { + "type": ["null", "string"] + }, + "tracking_url": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } } }, "spending_controls": { @@ -11341,21 +15156,33 @@ "properties": { "allowed_categories": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "blocked_categories": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } }, "spending_limits": { "type": ["null", "array"], - "items": { "type": ["null", "object"] } + "items": { + "type": ["null", "object"] + } }, - "spending_limits_currency": { "type": ["null", "string"] } + "spending_limits_currency": { + "type": ["null", "string"] + } } }, - "status": { "type": ["null", "string"] }, - "type": { "type": ["null", "string"] } + "status": { + "type": ["null", "string"] + }, + "type": { + "type": ["null", "string"] + } } }, "supported_sync_modes": ["full_refresh", "incremental"], @@ -11482,58 +15309,98 @@ "flight": { "type": ["null", "object"], "properties": { - "departure_at": { "type": ["null", "integer"] }, - "passenger_name": { "type": ["null", "string"] }, - "refundable": { "type": ["null", "boolean"] }, + "departure_at": { + "type": ["null", "integer"] + }, + "passenger_name": { + "type": ["null", "string"] + }, + "refundable": { + "type": ["null", "boolean"] + }, "segments": { "type": ["null", "array"], "items": { "type": ["null", "object"], "properties": { - "arrival_airport_code": { "type": ["null", "string"] }, - "carrier": { "type": ["null", "string"] }, + "arrival_airport_code": { + "type": ["null", "string"] + }, + "carrier": { + "type": ["null", "string"] + }, "departure_airport_code": { "type": ["null", "string"] }, - "flight_number": { "type": ["null", "string"] }, - "service_class": { "type": ["null", "string"] }, - "stopover_allowed": { "type": ["null", "boolean"] } + "flight_number": { + "type": ["null", "string"] + }, + "service_class": { + "type": ["null", "string"] + }, + "stopover_allowed": { + "type": ["null", "boolean"] + } } } } }, - "travel_agency": { "type": ["null", "string"] } + "travel_agency": { + "type": ["null", "string"] + } } }, "fuel": { "type": ["null", "object"], "properties": { - "type": { "type": ["null", "string"] }, - "unit": { "type": ["null", "string"] }, - "unit_cost_decimal": { "type": ["null", "string"] }, - "volume_decimal": { "type": ["null", "string"] } + "type": { + "type": ["null", "string"] + }, + "unit": { + "type": ["null", "string"] + }, + "unit_cost_decimal": { + "type": ["null", "string"] + }, + "volume_decimal": { + "type": ["null", "string"] + } } }, "lodging": { "type": ["null", "object"], "properties": { - "check_in_at": { "type": ["null", "integer"] }, - "nights": { "type": ["null", "integer"] } + "check_in_at": { + "type": ["null", "integer"] + }, + "nights": { + "type": ["null", "integer"] + } } }, "receipt": { "items": { "type": ["null", "object"], "properties": { - "description": { "type": ["null", "string"] }, - "quantity": { "type": ["null", "number"] }, - "total": { "type": ["null", "integer"] }, - "unit_cost": { "type": ["null", "integer"] } + "description": { + "type": ["null", "string"] + }, + "quantity": { + "type": ["null", "number"] + }, + "total": { + "type": ["null", "integer"] + }, + "unit_cost": { + "type": ["null", "integer"] + } } }, "type": ["null", "array"] }, - "reference": { "type": ["null", "string"] } + "reference": { + "type": ["null", "string"] + } }, "type": { "description": "The type of transaction, e.g., sale, refund, or dispute.", @@ -11893,7 +15760,9 @@ "products": { "description": "List of product IDs to which the coupon applies", "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } } } }, @@ -12429,51 +16298,105 @@ "price": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "active": { "type": ["null", "boolean"] }, - "billing_scheme": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "currency_options": { "type": ["null", "string"] }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "active": { + "type": ["null", "boolean"] + }, + "billing_scheme": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "currency_options": { + "type": ["null", "string"] + }, "custom_unit_amount": { "type": ["null", "object"], "properties": { - "maximum": { "type": ["null", "integer"] }, - "minimum": { "type": ["null", "integer"] }, - "preset": { "type": ["null", "integer"] } + "maximum": { + "type": ["null", "integer"] + }, + "minimum": { + "type": ["null", "integer"] + }, + "preset": { + "type": ["null", "integer"] + } } }, - "livemode": { "type": ["null", "boolean"] }, - "lookup_key": { "type": ["null", "string"] }, - "metadata": { "type": ["null", "object"] }, - "nickname": { "type": ["null", "string"] }, - "product": { "type": ["null", "string"] }, + "livemode": { + "type": ["null", "boolean"] + }, + "lookup_key": { + "type": ["null", "string"] + }, + "metadata": { + "type": ["null", "object"] + }, + "nickname": { + "type": ["null", "string"] + }, + "product": { + "type": ["null", "string"] + }, "recurring": { "type": ["null", "object"], "properties": { - "aggregate_usage": { "type": ["null", "string"] }, - "interval": { "type": ["null", "string"] }, - "interval_count": { "type": ["null", "integer"] }, - "usage_type": { "type": ["null", "string"] } + "aggregate_usage": { + "type": ["null", "string"] + }, + "interval": { + "type": ["null", "string"] + }, + "interval_count": { + "type": ["null", "integer"] + }, + "usage_type": { + "type": ["null", "string"] + } } }, - "tax_behavior": { "type": ["null", "string"] }, + "tax_behavior": { + "type": ["null", "string"] + }, "tiers": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } + }, + "tiers_mode": { + "type": ["null", "string"] }, - "tiers_mode": { "type": ["null", "string"] }, "transform_quantity": { "type": ["null", "object"], "properties": { - "divide_by": { "type": ["null", "integer"] }, - "round": { "type": ["null", "string"] } + "divide_by": { + "type": ["null", "integer"] + }, + "round": { + "type": ["null", "string"] + } } }, - "type": { "type": ["null", "string"] }, - "unit_amount": { "type": ["null", "integer"] }, - "unit_amount_decimal": { "type": ["null", "string"] } + "type": { + "type": ["null", "string"] + }, + "unit_amount": { + "type": ["null", "integer"] + }, + "unit_amount_decimal": { + "type": ["null", "string"] + } } }, "discount_amounts": { @@ -12506,21 +16429,51 @@ "items": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "active": { "type": ["null", "boolean"] }, - "country": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "description": { "type": ["null", "string"] }, - "display_name": { "type": ["null", "string"] }, - "effective_percentage": { "type": ["null", "number"] }, - "inclusive": { "type": ["null", "boolean"] }, - "jurisdiction": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"] }, - "percentage": { "type": ["null", "number"] }, - "state": { "type": ["null", "string"] }, - "tax_type": { "type": ["null", "string"] } + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "active": { + "type": ["null", "boolean"] + }, + "country": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "description": { + "type": ["null", "string"] + }, + "display_name": { + "type": ["null", "string"] + }, + "effective_percentage": { + "type": ["null", "number"] + }, + "inclusive": { + "type": ["null", "boolean"] + }, + "jurisdiction": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"] + }, + "percentage": { + "type": ["null", "number"] + }, + "state": { + "type": ["null", "string"] + }, + "tax_type": { + "type": ["null", "string"] + } } } }, @@ -12788,72 +16741,156 @@ "items": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "active": { "type": ["null", "boolean"] }, - "country": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "description": { "type": ["null", "string"] }, - "display_name": { "type": ["null", "string"] }, - "effective_percentage": { "type": ["null", "number"] }, - "inclusive": { "type": ["null", "boolean"] }, - "jurisdiction": { "type": ["null", "string"] }, - "livemode": { "type": ["null", "boolean"] }, - "metadata": { "type": ["null", "object"] }, - "percentage": { "type": ["null", "number"] }, - "state": { "type": ["null", "string"] }, - "tax_type": { "type": ["null", "string"] } + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "active": { + "type": ["null", "boolean"] + }, + "country": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "description": { + "type": ["null", "string"] + }, + "display_name": { + "type": ["null", "string"] + }, + "effective_percentage": { + "type": ["null", "number"] + }, + "inclusive": { + "type": ["null", "boolean"] + }, + "jurisdiction": { + "type": ["null", "string"] + }, + "livemode": { + "type": ["null", "boolean"] + }, + "metadata": { + "type": ["null", "object"] + }, + "percentage": { + "type": ["null", "number"] + }, + "state": { + "type": ["null", "string"] + }, + "tax_type": { + "type": ["null", "string"] + } } } }, "price": { "type": ["null", "object"], "properties": { - "id": { "type": ["null", "string"] }, - "object": { "type": ["null", "string"] }, - "active": { "type": ["null", "boolean"] }, - "billing_scheme": { "type": ["null", "string"] }, - "created": { "type": ["null", "integer"] }, - "currency": { "type": ["null", "string"] }, - "currency_options": { "type": ["null", "string"] }, + "id": { + "type": ["null", "string"] + }, + "object": { + "type": ["null", "string"] + }, + "active": { + "type": ["null", "boolean"] + }, + "billing_scheme": { + "type": ["null", "string"] + }, + "created": { + "type": ["null", "integer"] + }, + "currency": { + "type": ["null", "string"] + }, + "currency_options": { + "type": ["null", "string"] + }, "custom_unit_amount": { "type": ["null", "object"], "properties": { - "maximum": { "type": ["null", "integer"] }, - "minimum": { "type": ["null", "integer"] }, - "preset": { "type": ["null", "integer"] } + "maximum": { + "type": ["null", "integer"] + }, + "minimum": { + "type": ["null", "integer"] + }, + "preset": { + "type": ["null", "integer"] + } } }, - "livemode": { "type": ["null", "boolean"] }, - "lookup_key": { "type": ["null", "string"] }, - "metadata": { "type": ["null", "object"] }, - "nickname": { "type": ["null", "string"] }, - "product": { "type": ["null", "string"] }, + "livemode": { + "type": ["null", "boolean"] + }, + "lookup_key": { + "type": ["null", "string"] + }, + "metadata": { + "type": ["null", "object"] + }, + "nickname": { + "type": ["null", "string"] + }, + "product": { + "type": ["null", "string"] + }, "recurring": { "type": ["null", "object"], "properties": { - "aggregate_usage": { "type": ["null", "string"] }, - "interval": { "type": ["null", "string"] }, - "interval_count": { "type": ["null", "integer"] }, - "usage_type": { "type": ["null", "string"] } + "aggregate_usage": { + "type": ["null", "string"] + }, + "interval": { + "type": ["null", "string"] + }, + "interval_count": { + "type": ["null", "integer"] + }, + "usage_type": { + "type": ["null", "string"] + } } }, - "tax_behavior": { "type": ["null", "string"] }, + "tax_behavior": { + "type": ["null", "string"] + }, "tiers": { "type": ["null", "array"], - "items": { "type": ["null", "string"] } + "items": { + "type": ["null", "string"] + } + }, + "tiers_mode": { + "type": ["null", "string"] }, - "tiers_mode": { "type": ["null", "string"] }, "transform_quantity": { "type": ["null", "object"], "properties": { - "divide_by": { "type": ["null", "integer"] }, - "round": { "type": ["null", "string"] } + "divide_by": { + "type": ["null", "integer"] + }, + "round": { + "type": ["null", "string"] + } } }, - "type": { "type": ["null", "string"] }, - "unit_amount": { "type": ["null", "integer"] }, - "unit_amount_decimal": { "type": ["null", "string"] } + "type": { + "type": ["null", "string"] + }, + "unit_amount": { + "type": ["null", "integer"] + }, + "unit_amount_decimal": { + "type": ["null", "string"] + } } }, "updated": { diff --git a/airbyte-integrations/connectors/source-stripe/integration_tests/__init__.py b/airbyte-integrations/connectors/source-stripe/integration_tests/__init__.py index c941b30457953..2acb8555b306c 100644 --- a/airbyte-integrations/connectors/source-stripe/integration_tests/__init__.py +++ b/airbyte-integrations/connectors/source-stripe/integration_tests/__init__.py @@ -1,3 +1,3 @@ # -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. # 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 2f1fc983ccb86..4c534e155285b 100644 --- a/airbyte-integrations/connectors/source-stripe/integration_tests/abnormal_state.json +++ b/airbyte-integrations/connectors/source-stripe/integration_tests/abnormal_state.json @@ -65,7 +65,7 @@ { "type": "STREAM", "stream": { - "stream_state": { "updated": 10000000000 }, + "stream_state": { "updated": 1577836800 }, "stream_descriptor": { "name": "customers" } } }, @@ -282,7 +282,7 @@ { "type": "STREAM", "stream": { - "stream_state": { "updated": 10000000000 }, + "stream_state": { "updated": 1720010734 }, "stream_descriptor": { "name": "payment_methods" } } }, @@ -296,14 +296,14 @@ { "type": "STREAM", "stream": { - "stream_state": { "created": 10000000000 }, + "stream_state": { "created": 1646998902 }, "stream_descriptor": { "name": "customer_balance_transactions" } } }, { "type": "STREAM", "stream": { - "stream_state": { "updated": 10000000000 }, + "stream_state": { "updated": 1588291200 }, "stream_descriptor": { "name": "accounts" } } }, diff --git a/airbyte-integrations/connectors/source-stripe/integration_tests/acceptance.py b/airbyte-integrations/connectors/source-stripe/integration_tests/acceptance.py index fbed37992cb4f..80c94b1a58c89 100644 --- a/airbyte-integrations/connectors/source-stripe/integration_tests/acceptance.py +++ b/airbyte-integrations/connectors/source-stripe/integration_tests/acceptance.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. # diff --git a/airbyte-integrations/connectors/source-stripe/integration_tests/expected_records.jsonl b/airbyte-integrations/connectors/source-stripe/integration_tests/expected_records.jsonl index 87f54ffd035c1..3a5c0b4539599 100644 --- a/airbyte-integrations/connectors/source-stripe/integration_tests/expected_records.jsonl +++ b/airbyte-integrations/connectors/source-stripe/integration_tests/expected_records.jsonl @@ -8,7 +8,7 @@ {"stream": "accounts", "data": {"id": "acct_1MwD6tIyVv44cUB4", "object": "account", "business_profile": {"annual_revenue": null,"estimated_worker_count": null,"mcc": null, "name": null, "product_description": null, "support_address": null, "support_email": null, "support_phone": null, "support_url": null, "url": null}, "business_type": null, "capabilities": {"card_payments": "inactive", "transfers": "inactive"}, "charges_enabled": false, "country": "US", "created": 1681342196, "default_currency": "usd", "details_submitted": false, "email": "jenny.rosen@example.com", "external_accounts": {"object": "list", "data": [], "has_more": false, "total_count": 0, "url": "/v1/accounts/acct_1MwD6tIyVv44cUB4/external_accounts"}, "future_requirements": {"alternatives": [], "current_deadline": null, "currently_due": [], "disabled_reason": null, "errors": [], "eventually_due": [], "past_due": [], "pending_verification": []}, "metadata": {}, "payouts_enabled": false, "requirements": {"alternatives": [], "current_deadline": null, "currently_due": ["business_profile.mcc", "business_profile.url", "business_type", "external_account", "representative.first_name", "representative.last_name", "tos_acceptance.date", "tos_acceptance.ip"], "disabled_reason": "requirements.past_due", "errors": [], "eventually_due": ["business_profile.mcc", "business_profile.url", "business_type", "external_account", "representative.first_name", "representative.last_name", "tos_acceptance.date", "tos_acceptance.ip"], "past_due": ["business_profile.mcc", "business_profile.url", "business_type", "external_account", "representative.first_name", "representative.last_name", "tos_acceptance.date", "tos_acceptance.ip"], "pending_verification": []}, "settings": {"bacs_debit_payments": {"display_name": null, "service_user_number": null}, "branding": {"icon": null, "logo": null, "primary_color": null, "secondary_color": null}, "card_issuing": {"tos_acceptance": {"date": null, "ip": null}}, "card_payments": {"decline_on": {"avs_failure": false, "cvc_failure": false}, "statement_descriptor_prefix": null, "statement_descriptor_prefix_kana": null, "statement_descriptor_prefix_kanji": null}, "dashboard": {"display_name": null, "timezone": "Etc/UTC"}, "invoices": {"default_account_tax_ids": null}, "payments": {"statement_descriptor": null, "statement_descriptor_kana": null, "statement_descriptor_kanji": null}, "payouts": {"debit_negative_balances": false, "schedule": {"delay_days": 2, "interval": "daily"}, "statement_descriptor": null}, "sepa_debit_payments": {}}, "tos_acceptance": {"date": null, "ip": null, "user_agent": null}, "type": "custom"}, "emitted_at": 1697627267882} {"stream": "accounts", "data": {"id": "acct_1Jx8unEYmRTj5on1", "object": "account", "business_profile": {"annual_revenue": null,"estimated_worker_count": null,"mcc": null, "name": "Airbyte", "support_address": null, "support_email": null, "support_phone": null, "support_url": null, "url": null}, "capabilities": {}, "charges_enabled": false, "controller": {"type": "account"}, "country": "US", "default_currency": "usd", "details_submitted": false, "email": null, "future_requirements": {"alternatives": [], "current_deadline": null, "currently_due": [], "disabled_reason": null, "errors": [], "eventually_due": [], "past_due": [], "pending_verification": []}, "metadata": {}, "payouts_enabled": false, "requirements": {"alternatives": [], "current_deadline": null, "currently_due": ["business_profile.product_description", "business_profile.support_phone", "business_profile.url", "external_account", "tos_acceptance.date", "tos_acceptance.ip"], "disabled_reason": "requirements.past_due", "errors": [], "eventually_due": ["business_profile.product_description", "business_profile.support_phone", "business_profile.url", "external_account", "tos_acceptance.date", "tos_acceptance.ip"], "past_due": [], "pending_verification": []}, "settings": {"bacs_debit_payments": {"display_name": null, "service_user_number": null}, "branding": {"icon": null, "logo": null, "primary_color": null, "secondary_color": null}, "card_issuing": {"tos_acceptance": {"date": null, "ip": null}}, "card_payments": {"statement_descriptor_prefix": null, "statement_descriptor_prefix_kana": null, "statement_descriptor_prefix_kanji": null}, "dashboard": {"display_name": null, "timezone": "Etc/UTC"}, "invoices": {"default_account_tax_ids": null}, "payments": {"statement_descriptor": null, "statement_descriptor_kana": null, "statement_descriptor_kanji": null}, "sepa_debit_payments": {}}, "type": "standard"}, "emitted_at": 1697627267884} {"stream": "accounts", "data": {"id": "acct_1HRPLyCpK2Z3jTFF", "object": "account", "capabilities": {"acss_debit_payments": "inactive", "afterpay_clearpay_payments": "inactive", "bancontact_payments": "inactive", "card_payments": "inactive", "eps_payments": "inactive", "giropay_payments": "inactive", "ideal_payments": "inactive", "p24_payments": "inactive", "sepa_debit_payments": "inactive", "sofort_payments": "inactive", "transfers": "inactive"}, "charges_enabled": false, "country": "US", "default_currency": "usd", "details_submitted": false, "future_requirements": {"alternatives": [], "current_deadline": null, "currently_due": [], "disabled_reason": null, "errors": [], "eventually_due": [], "past_due": [], "pending_verification": []}, "payouts_enabled": false, "requirements": {"alternatives": [], "current_deadline": null, "currently_due": ["business_profile.mcc", "business_profile.product_description", "business_profile.support_phone", "business_profile.url", "external_account", "individual.dob.day", "individual.dob.month", "individual.dob.year", "individual.email", "individual.first_name", "individual.last_name", "individual.phone", "individual.ssn_last_4", "tos_acceptance.date", "tos_acceptance.ip"], "disabled_reason": "requirements.past_due", "errors": [], "eventually_due": ["business_profile.mcc", "business_profile.product_description", "business_profile.support_phone", "business_profile.url", "external_account", "individual.dob.day", "individual.dob.month", "individual.dob.year", "individual.email", "individual.first_name", "individual.last_name", "individual.phone", "individual.ssn_last_4", "tos_acceptance.date", "tos_acceptance.ip"], "past_due": ["business_profile.mcc", "business_profile.product_description", "business_profile.support_phone", "business_profile.url", "external_account", "individual.dob.day", "individual.dob.month", "individual.dob.year", "individual.email", "individual.first_name", "individual.last_name", "individual.phone", "individual.ssn_last_4", "tos_acceptance.date", "tos_acceptance.ip"], "pending_verification": []}, "settings": {"bacs_debit_payments": {"display_name": null, "service_user_number": null}, "branding": {"icon": null, "logo": null, "primary_color": null, "secondary_color": null}, "card_issuing": {"tos_acceptance": {"date": null, "ip": null}}, "card_payments": {"statement_descriptor_prefix": null, "statement_descriptor_prefix_kana": null, "statement_descriptor_prefix_kanji": null}, "dashboard": {"display_name": null, "timezone": "America/Los_Angeles"}, "invoices": {"default_account_tax_ids": null}, "payments": {"statement_descriptor": null, "statement_descriptor_kana": null, "statement_descriptor_kanji": null}, "sepa_debit_payments": {}}, "type": "standard"}, "emitted_at": 1707141120832} -{"stream": "shipping_rates", "data": {"id": "shr_1NXgplEcXtiJtvvhA1ntV782", "object": "shipping_rate", "active": true, "created": 1690274589, "delivery_estimate": "{'maximum': {'unit': 'business_day', 'value': 14}, 'minimum': {'unit': 'business_day', 'value': 10}}", "display_name": "Test Ground Shipping", "fixed_amount": {"amount": 999, "currency": "usd"}, "livemode": false, "metadata": {}, "tax_behavior": "inclusive", "tax_code": "txcd_92010001", "type": "fixed_amount"}, "emitted_at": 1697627269309} +{"stream":"shipping_rates","data":{"id":"shr_1NXgplEcXtiJtvvhA1ntV782","object":"shipping_rate","active":true,"created":1690274589,"delivery_estimate":{"maximum":{"unit":"business_day","value":14},"minimum":{"unit":"business_day","value":10}},"display_name":"Test Ground Shipping","fixed_amount":{"amount":999,"currency":"usd"},"livemode":false,"metadata":{},"tax_behavior":"inclusive","tax_code":"txcd_92010001","type":"fixed_amount"},"emitted_at":1740090575020} {"stream": "balance_transactions", "data": {"id": "txn_1KVQhfEcXtiJtvvhF7ox3YEm", "object": "balance_transaction", "amount": -9164, "available_on": 1645488000, "created": 1645406919, "currency": "usd", "description": "STRIPE PAYOUT", "exchange_rate": null, "fee": 0, "fee_details": [], "net": -9164, "reporting_category": "payout", "source": "po_1KVQhfEcXtiJtvvhZlUkl08U", "status": "available", "type": "payout"}, "emitted_at": 1697627270253} {"stream": "balance_transactions", "data": {"id": "txn_3K9FSOEcXtiJtvvh0KoS5mx7", "object": "balance_transaction", "amount": 5300, "available_on": 1640649600, "created": 1640120473, "currency": "usd", "description": null, "exchange_rate": null, "fee": 184, "fee_details": [{"amount": 184, "application": null, "currency": "usd", "description": "Stripe processing fees", "type": "stripe_fee"}], "net": 5116, "reporting_category": "charge", "source": "ch_3K9FSOEcXtiJtvvh0zxb7clc", "status": "available", "type": "charge"}, "emitted_at": 1697627270254} {"stream": "balance_transactions", "data": {"id": "txn_3K9F5DEcXtiJtvvh1qsqmHcH", "object": "balance_transaction", "amount": 4200, "available_on": 1640649600, "created": 1640119035, "currency": "usd", "description": "edgao test", "exchange_rate": null, "fee": 152, "fee_details": [{"amount": 152, "application": null, "currency": "usd", "description": "Stripe processing fees", "type": "stripe_fee"}], "net": 4048, "reporting_category": "charge", "source": "ch_3K9F5DEcXtiJtvvh1w2MaTpj", "status": "available", "type": "charge"}, "emitted_at": 1697627270255} diff --git a/airbyte-integrations/connectors/source-stripe/main.py b/airbyte-integrations/connectors/source-stripe/main.py index e81b1f8f0da51..25c030b88d359 100644 --- a/airbyte-integrations/connectors/source-stripe/main.py +++ b/airbyte-integrations/connectors/source-stripe/main.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. # diff --git a/airbyte-integrations/connectors/source-stripe/metadata.yaml b/airbyte-integrations/connectors/source-stripe/metadata.yaml index d7a965f0924fc..16fd1b292be37 100644 --- a/airbyte-integrations/connectors/source-stripe/metadata.yaml +++ b/airbyte-integrations/connectors/source-stripe/metadata.yaml @@ -10,7 +10,7 @@ data: connectorSubtype: api connectorType: source definitionId: e094cb9a-26de-4645-8761-65c0c425d1de - dockerImageTag: 5.8.12 + dockerImageTag: 5.9.0-rc.1 dockerRepository: airbyte/source-stripe documentationUrl: https://docs.airbyte.com/integrations/sources/stripe erdUrl: https://dbdocs.io/airbyteio/source-stripe?view=relationships @@ -55,7 +55,7 @@ data: supportLevel: certified tags: - language:python - - cdk:python + - cdk:low-code connectorTestSuitesOptions: - suite: liveTests testConnections: diff --git a/airbyte-integrations/connectors/source-stripe/poetry.lock b/airbyte-integrations/connectors/source-stripe/poetry.lock index 8eeac7297b499..d8b15ca81dc0b 100644 --- a/airbyte-integrations/connectors/source-stripe/poetry.lock +++ b/airbyte-integrations/connectors/source-stripe/poetry.lock @@ -1,16 +1,14 @@ -# This file is automatically @generated by Poetry 2.0.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 = "6.38.4" +version = "6.41.1" description = "A framework for writing Airbyte Connectors." optional = false python-versions = "<3.13,>=3.10" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ - {file = "airbyte_cdk-6.38.4-py3-none-any.whl", hash = "sha256:78e142d61da7fa763b98caee211fabbbb13853b76725c9e56eb773ed2aa6e261"}, - {file = "airbyte_cdk-6.38.4.tar.gz", hash = "sha256:29a9bc96f67aa9a15ed23d880e33e7925481dc7d06b13e432e937dc15da18769"}, + {file = "airbyte_cdk-6.41.1-py3-none-any.whl", hash = "sha256:1fefae879211822cab2877dc146a7911b88b6e925da690e8a5d5ae4e2fbcb579"}, + {file = "airbyte_cdk-6.41.1.tar.gz", hash = "sha256:a444ccfa456e3e4753920e2b2f5454179cbd189e6ee3fef75520cedaacb819c8"}, ] [package.dependencies] @@ -30,6 +28,7 @@ langchain_core = "0.1.42" nltk = "3.9.1" numpy = "<2" orjson = ">=3.10.7,<4.0.0" +packaging = "*" pandas = "2.2.2" psutil = "6.1.0" pydantic = ">=2.7,<3.0" @@ -43,6 +42,7 @@ rapidfuzz = ">=3.10.1,<4.0.0" requests = "*" requests_cache = "*" serpyco-rs = ">=1.10.2,<2.0.0" +typing-extensions = "*" wcmatch = "10.0" whenever = ">=0.6.16,<0.7.0" xmltodict = ">=0.13,<0.15" @@ -58,8 +58,6 @@ version = "0.14.2" description = "Declares the Airbyte Protocol using Python Dataclasses. Dataclasses in Python have less performance overhead compared to Pydantic models, making them a more efficient choice for scenarios where speed and memory usage are critical" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "airbyte_protocol_models_dataclasses-0.14.2-py3-none-any.whl", hash = "sha256:ae06a406df031afa42f1156bacc587958197e5c7d9bbaf11893480903d4ded8b"}, {file = "airbyte_protocol_models_dataclasses-0.14.2.tar.gz", hash = "sha256:9279237156b722cdd54e7b9ec8f97d264bd96e3f3008bc5fc47c215288a2212a"}, @@ -71,8 +69,6 @@ version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -84,8 +80,6 @@ version = "0.3.2" description = "Unicode to ASCII transliteration" optional = false python-versions = ">=3.3" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "anyascii-0.3.2-py3-none-any.whl", hash = "sha256:3b3beef6fc43d9036d3b0529050b0c48bfad8bc960e9e562d7223cfb94fe45d4"}, {file = "anyascii-0.3.2.tar.gz", hash = "sha256:9d5d32ef844fe225b8bc7cba7f950534fae4da27a9bf3a6bea2cb0ea46ce4730"}, @@ -97,8 +91,6 @@ version = "4.8.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.9" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"}, {file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"}, @@ -121,8 +113,6 @@ version = "0.4.0" description = "PEP 224 implementation" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "attributes-doc-0.4.0.tar.gz", hash = "sha256:b1576c94a714e9fc2c65c47cf10d0c8e1a5f7c4f5ae7f69006be108d95cbfbfb"}, {file = "attributes_doc-0.4.0-py2.py3-none-any.whl", hash = "sha256:4c3007d9e58f3a6cb4b9c614c4d4ce2d92161581f28e594ddd8241cc3a113bdd"}, @@ -130,22 +120,20 @@ files = [ [[package]] name = "attrs" -version = "25.1.0" +version = "25.3.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ - {file = "attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a"}, - {file = "attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e"}, + {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, + {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, ] [package.extras] benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] @@ -155,8 +143,6 @@ version = "2.2.1" description = "Function decoration for backoff and retry" optional = false python-versions = ">=3.7,<4.0" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, @@ -168,8 +154,6 @@ version = "2.5.post1" description = "Bash style brace expander." optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "bracex-2.5.post1-py3-none-any.whl", hash = "sha256:13e5732fec27828d6af308628285ad358047cec36801598368cb28bc631dbaf6"}, {file = "bracex-2.5.post1.tar.gz", hash = "sha256:12c50952415bfa773d2d9ccb8e79651b8cdb1f31a42f6091b804f6ba2b4a66b6"}, @@ -181,8 +165,6 @@ version = "5.5.2" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.7" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a"}, {file = "cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4"}, @@ -194,8 +176,6 @@ version = "24.1.2" description = "Composable complex class support for attrs and dataclasses." optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "cattrs-24.1.2-py3-none-any.whl", hash = "sha256:67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0"}, {file = "cattrs-24.1.2.tar.gz", hash = "sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85"}, @@ -222,8 +202,6 @@ version = "2025.1.31" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" -groups = ["main", "dev"] -markers = "python_version <= \"3.11\"" files = [ {file = "certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe"}, {file = "certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651"}, @@ -235,8 +213,6 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\" and platform_python_implementation != \"PyPy\"" files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -316,8 +292,6 @@ version = "3.4.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" -groups = ["main", "dev"] -markers = "python_version <= \"3.11\"" files = [ {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, @@ -419,8 +393,6 @@ version = "8.1.8" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, @@ -435,12 +407,10 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -groups = ["main", "dev"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -markers = {main = "python_version <= \"3.11\" and platform_system == \"Windows\"", dev = "python_version <= \"3.11\" and sys_platform == \"win32\""} [[package]] name = "cryptography" @@ -448,8 +418,6 @@ version = "44.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = "!=3.9.0,!=3.9.1,>=3.7" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "cryptography-44.0.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:efcfe97d1b3c79e486554efddeb8f6f53a4cdd4cf6086642784fa31fc384e1d7"}, {file = "cryptography-44.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29ecec49f3ba3f3849362854b7253a9f59799e3763b0c9d0826259a88efa02f1"}, @@ -507,8 +475,6 @@ version = "2.2.0" description = "Filesystem-like pathing and searching for dictionaries" optional = false python-versions = ">=3.7" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "dpath-2.2.0-py3-none-any.whl", hash = "sha256:b330a375ded0a0d2ed404440f6c6a715deae5313af40bbb01c8a41d891900576"}, {file = "dpath-2.2.0.tar.gz", hash = "sha256:34f7e630dc55ea3f219e555726f5da4b4b25f2200319c8e6902c394258dd6a3e"}, @@ -520,8 +486,6 @@ version = "1.23.0" description = "Dynamic version generation" optional = false python-versions = ">=3.5" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "dunamai-1.23.0-py3-none-any.whl", hash = "sha256:a0906d876e92441793c6a423e16a4802752e723e9c9a5aabdc5535df02dbe041"}, {file = "dunamai-1.23.0.tar.gz", hash = "sha256:a163746de7ea5acb6dacdab3a6ad621ebc612ed1e528aaa8beedb8887fccd2c4"}, @@ -536,8 +500,6 @@ version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" -groups = ["main", "dev"] -markers = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, @@ -552,8 +514,6 @@ version = "1.2.2" description = "Let your Python tests travel through time" optional = false python-versions = ">=3.6" -groups = ["dev"] -markers = "python_version <= \"3.11\"" files = [ {file = "freezegun-1.2.2-py3-none-any.whl", hash = "sha256:ea1b963b993cb9ea195adbd893a48d573fda951b0da64f60883d7e988b606c9f"}, {file = "freezegun-1.2.2.tar.gz", hash = "sha256:cd22d1ba06941384410cd967d8a99d5ae2442f57dfafeff2fda5de8dc5c05446"}, @@ -568,8 +528,6 @@ version = "1.3.0" description = "GenSON is a powerful, user-friendly JSON Schema generator." optional = false python-versions = "*" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "genson-1.3.0-py3-none-any.whl", hash = "sha256:468feccd00274cc7e4c09e84b08704270ba8d95232aa280f65b986139cec67f7"}, {file = "genson-1.3.0.tar.gz", hash = "sha256:e02db9ac2e3fd29e65b5286f7135762e2cd8a986537c075b06fc5f1517308e37"}, @@ -581,8 +539,6 @@ version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false python-versions = ">=3.7" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, @@ -594,8 +550,6 @@ version = "1.0.7" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, @@ -617,8 +571,6 @@ version = "0.28.1" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, @@ -643,8 +595,6 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" -groups = ["main", "dev"] -markers = "python_version <= \"3.11\"" files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -659,8 +609,6 @@ version = "2.0.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.7" -groups = ["dev"] -markers = "python_version <= \"3.11\"" files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, @@ -672,8 +620,6 @@ version = "0.6.1" description = "An ISO 8601 date/time/duration parser and formatter" optional = false python-versions = "*" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "isodate-0.6.1-py2.py3-none-any.whl", hash = "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96"}, {file = "isodate-0.6.1.tar.gz", hash = "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9"}, @@ -688,8 +634,6 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -707,8 +651,6 @@ version = "1.4.2" description = "Lightweight pipelining with Python functions" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6"}, {file = "joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e"}, @@ -720,8 +662,6 @@ version = "1.33" description = "Apply JSON-Patches (RFC 6902)" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, @@ -736,8 +676,6 @@ version = "3.0.0" description = "Identify specific nodes in a JSON document (RFC 6901)" optional = false python-versions = ">=3.7" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"}, {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"}, @@ -749,8 +687,6 @@ version = "0.2" description = "An implementation of JSON Reference for Python" optional = false python-versions = "*" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "jsonref-0.2-py3-none-any.whl", hash = "sha256:b1e82fa0b62e2c2796a13e5401fe51790b248f6d9bf9d7212a3e31a3501b291f"}, {file = "jsonref-0.2.tar.gz", hash = "sha256:f3c45b121cf6257eafabdc3a8008763aed1cd7da06dbabc59a9e4d2a5e4e6697"}, @@ -762,8 +698,6 @@ version = "4.17.3" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.7" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, @@ -783,8 +717,6 @@ version = "0.1.42" description = "Building applications with LLMs through composability" optional = false python-versions = "<4.0,>=3.8.1" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "langchain_core-0.1.42-py3-none-any.whl", hash = "sha256:c5653ffa08a44f740295c157a24c0def4a753333f6a2c41f76bf431cd00be8b5"}, {file = "langchain_core-0.1.42.tar.gz", hash = "sha256:40751bf60ea5d8e2b2efe65290db434717ee3834870c002e40e2811f09d814e6"}, @@ -807,8 +739,6 @@ version = "0.1.147" description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." optional = false python-versions = "<4.0,>=3.8.1" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "langsmith-0.1.147-py3-none-any.whl", hash = "sha256:7166fc23b965ccf839d64945a78e9f1157757add228b086141eb03a60d699a15"}, {file = "langsmith-0.1.147.tar.gz", hash = "sha256:2e933220318a4e73034657103b3b1a3a6109cc5db3566a7e8e03be8d6d7def7a"}, @@ -830,8 +760,6 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -902,8 +830,6 @@ version = "3.9.1" description = "Natural Language Toolkit" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "nltk-3.9.1-py3-none-any.whl", hash = "sha256:4fa26829c5b00715afe3061398a8989dc643b92ce7dd93fb4585a70930d168a1"}, {file = "nltk-3.9.1.tar.gz", hash = "sha256:87d127bd3de4bd89a4f81265e5fa59cb1b199b27440175370f7417d2bc7ae868"}, @@ -929,8 +855,6 @@ version = "1.26.4" description = "Fundamental package for array computing in Python" optional = false python-versions = ">=3.9" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, @@ -976,8 +900,6 @@ version = "3.10.15" description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "orjson-3.10.15-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:552c883d03ad185f720d0c09583ebde257e41b9521b74ff40e08b7dec4559c04"}, {file = "orjson-3.10.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:616e3e8d438d02e4854f70bfdc03a6bcdb697358dbaa6bcd19cbe24d24ece1f8"}, @@ -1066,8 +988,6 @@ version = "23.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.7" -groups = ["main", "dev"] -markers = "python_version <= \"3.11\"" files = [ {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, @@ -1079,8 +999,6 @@ version = "2.2.2" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.9" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"}, {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"}, @@ -1153,8 +1071,6 @@ version = "2.1.2" description = "Python datetimes made easy" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "pendulum-2.1.2-cp27-cp27m-macosx_10_15_x86_64.whl", hash = "sha256:b6c352f4bd32dff1ea7066bd31ad0f71f8d8100b9ff709fb343f3b86cee43efe"}, {file = "pendulum-2.1.2-cp27-cp27m-win_amd64.whl", hash = "sha256:318f72f62e8e23cd6660dbafe1e346950281a9aed144b5c596b2ddabc1d19739"}, @@ -1189,8 +1105,6 @@ version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, @@ -1207,8 +1121,6 @@ version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -1224,8 +1136,6 @@ version = "6.1.0" description = "Cross-platform lib for process and system monitoring in Python." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "psutil-6.1.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ff34df86226c0227c52f38b919213157588a678d049688eded74c76c8ba4a5d0"}, {file = "psutil-6.1.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:c0e0c00aa18ca2d3b2b991643b799a15fc8f0563d2ebb6040f64ce8dc027b942"}, @@ -1256,8 +1166,6 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\" and platform_python_implementation != \"PyPy\"" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -1269,8 +1177,6 @@ version = "2.10.6" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, @@ -1291,8 +1197,6 @@ version = "2.27.2" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, @@ -1405,8 +1309,6 @@ version = "2.10.1" description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.9" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, @@ -1424,8 +1326,6 @@ version = "3.1.1" description = "Python Rate-Limiter using Leaky-Bucket Algorithm" optional = false python-versions = ">=3.8,<4.0" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "pyrate_limiter-3.1.1-py3-none-any.whl", hash = "sha256:c51906f1d51d56dc992ff6c26e8300e32151bc6cfa3e6559792e31971dfd4e2b"}, {file = "pyrate_limiter-3.1.1.tar.gz", hash = "sha256:2f57eda712687e6eccddf6afe8f8a15b409b97ed675fe64a626058f12863b7b7"}, @@ -1441,8 +1341,6 @@ version = "0.20.0" description = "Persistent/Functional/Immutable data structures" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "pyrsistent-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c3aba3e01235221e5b229a6c05f585f344734bd1ad42a8ac51493d74722bbce"}, {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1beb78af5423b879edaf23c5591ff292cf7c33979734c99aa66d5914ead880f"}, @@ -1484,8 +1382,6 @@ version = "8.3.5" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" files = [ {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, @@ -1508,8 +1404,6 @@ version = "3.14.0" description = "Thin-wrapper around the mock package for easier use with pytest" optional = false python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version <= \"3.11\"" files = [ {file = "pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0"}, {file = "pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f"}, @@ -1527,8 +1421,6 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main", "dev"] -markers = "python_version <= \"3.11\"" files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -1543,8 +1435,6 @@ version = "3.0.0" description = "Universally unique lexicographically sortable identifier" optional = false python-versions = ">=3.9" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "python_ulid-3.0.0-py3-none-any.whl", hash = "sha256:e4c4942ff50dbd79167ad01ac725ec58f924b4018025ce22c858bfcff99a5e31"}, {file = "python_ulid-3.0.0.tar.gz", hash = "sha256:e50296a47dc8209d28629a22fc81ca26c00982c78934bd7766377ba37ea49a9f"}, @@ -1559,8 +1449,6 @@ version = "2024.2" description = "World timezone definitions, modern and historical" optional = false python-versions = "*" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725"}, {file = "pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a"}, @@ -1572,8 +1460,6 @@ version = "2020.1" description = "The Olson timezone database for Python." optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "pytzdata-2020.1-py2.py3-none-any.whl", hash = "sha256:e1e14750bcf95016381e4d472bad004eef710f2d6417240904070b3d6654485f"}, {file = "pytzdata-2020.1.tar.gz", hash = "sha256:3efa13b335a00a8de1d345ae41ec78dd11c9f8807f522d39850f2dd828681540"}, @@ -1585,8 +1471,6 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -1649,8 +1533,6 @@ version = "3.12.2" description = "rapid fuzzy string matching" optional = false python-versions = ">=3.9" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "rapidfuzz-3.12.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0b9a75e0385a861178adf59e86d6616cbd0d5adca7228dc9eeabf6f62cf5b0b1"}, {file = "rapidfuzz-3.12.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6906a7eb458731e3dd2495af1d0410e23a21a2a2b7ced535e6d5cd15cb69afc5"}, @@ -1757,8 +1639,6 @@ version = "2024.11.6" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"}, {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"}, @@ -1862,8 +1742,6 @@ version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" -groups = ["main", "dev"] -markers = "python_version <= \"3.11\"" files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, @@ -1885,8 +1763,6 @@ version = "1.2.1" description = "A persistent cache for python requests" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "requests_cache-1.2.1-py3-none-any.whl", hash = "sha256:1285151cddf5331067baa82598afe2d47c7495a1334bfe7a7d329b43e9fd3603"}, {file = "requests_cache-1.2.1.tar.gz", hash = "sha256:68abc986fdc5b8d0911318fbb5f7c80eebcd4d01bfacc6685ecf8876052511d1"}, @@ -1917,8 +1793,6 @@ version = "1.12.1" description = "Mock out responses from the requests package" optional = false python-versions = ">=3.5" -groups = ["dev"] -markers = "python_version <= \"3.11\"" files = [ {file = "requests-mock-1.12.1.tar.gz", hash = "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401"}, {file = "requests_mock-1.12.1-py2.py3-none-any.whl", hash = "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563"}, @@ -1936,8 +1810,6 @@ version = "1.0.0" description = "A utility belt for advanced users of python-requests" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6"}, {file = "requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06"}, @@ -1952,8 +1824,6 @@ version = "1.13.0" description = "" optional = false python-versions = ">=3.9" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "serpyco_rs-1.13.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e722b3053e627d8a304e462bce20cae1670a2c4b0ef875b84d0de0081bec4029"}, {file = "serpyco_rs-1.13.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f10e89c752ff78d720a42e026b0a9ada70717ad6306a9356f794280167d62bf"}, @@ -2008,8 +1878,6 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -groups = ["main", "dev"] -markers = "python_version <= \"3.11\"" files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, @@ -2021,8 +1889,6 @@ version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -2034,8 +1900,6 @@ version = "8.5.0" description = "Retry code until it succeeds" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687"}, {file = "tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78"}, @@ -2051,8 +1915,6 @@ version = "2.2.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" -groups = ["dev"] -markers = "python_version < \"3.11\"" files = [ {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, @@ -2094,8 +1956,6 @@ version = "4.67.1" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2"}, {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, @@ -2117,8 +1977,6 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -2130,8 +1988,6 @@ version = "2025.1" description = "Provider of IANA time zone data" optional = false python-versions = ">=2" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639"}, {file = "tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694"}, @@ -2143,8 +1999,6 @@ version = "1.4.3" description = "URL normalization for Python" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "url-normalize-1.4.3.tar.gz", hash = "sha256:d23d3a070ac52a67b83a1c59a0e68f8608d1cd538783b401bc9de2c0fac999b2"}, {file = "url_normalize-1.4.3-py2.py3-none-any.whl", hash = "sha256:ec3c301f04e5bb676d333a7fa162fa977ad2ca04b7e652bfc9fac4e405728eed"}, @@ -2159,8 +2013,6 @@ version = "2.3.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" -groups = ["main", "dev"] -markers = "python_version <= \"3.11\"" files = [ {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, @@ -2178,8 +2030,6 @@ version = "10.0" description = "Wildcard/glob file name matcher." optional = false python-versions = ">=3.8" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "wcmatch-10.0-py3-none-any.whl", hash = "sha256:0dd927072d03c0a6527a20d2e6ad5ba8d0380e60870c383bc533b71744df7b7a"}, {file = "wcmatch-10.0.tar.gz", hash = "sha256:e72f0de09bba6a04e0de70937b0cf06e55f36f37b3deb422dfaf854b867b840a"}, @@ -2194,8 +2044,6 @@ version = "0.6.17" description = "Modern datetime library for Python" optional = false python-versions = ">=3.9" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "whenever-0.6.17-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:8e9e905fd19b0679e5ab1a0d0110a1974b89bf4cbd1ff22c9e352db381e4ae4f"}, {file = "whenever-0.6.17-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cd615e60f992fb9ae9d73fc3581ac63de981e51013b0fffbf8e2bd748c71e3df"}, @@ -2279,14 +2127,12 @@ version = "0.14.2" description = "Makes working with XML feel like you are working with JSON" optional = false python-versions = ">=3.6" -groups = ["main"] -markers = "python_version <= \"3.11\"" files = [ {file = "xmltodict-0.14.2-py2.py3-none-any.whl", hash = "sha256:20cc7d723ed729276e808f26fb6b3599f786cbc37e06c65e192ba77c40f20aac"}, {file = "xmltodict-0.14.2.tar.gz", hash = "sha256:201e7c28bb210e374999d1dde6382923ab0ed1a8a5faeece48ab525b7810a553"}, ] [metadata] -lock-version = "2.1" +lock-version = "2.0" python-versions = "^3.10,<3.12" content-hash = "32c7d63f90e8c6453cb810362965213dd072aa0bcdab027572eedc3c8a392a0e" diff --git a/airbyte-integrations/connectors/source-stripe/pyproject.toml b/airbyte-integrations/connectors/source-stripe/pyproject.toml index b133d0a38681f..ef4a969215561 100644 --- a/airbyte-integrations/connectors/source-stripe/pyproject.toml +++ b/airbyte-integrations/connectors/source-stripe/pyproject.toml @@ -3,7 +3,7 @@ requires = [ "poetry-core>=1.0.0",] build-backend = "poetry.core.masonry.api" [tool.poetry] -version = "5.8.12" +version = "5.9.0-rc.1" name = "source-stripe" description = "Source implementation for Stripe." authors = [ "Airbyte ",] diff --git a/airbyte-integrations/connectors/source-stripe/source_stripe/__init__.py b/airbyte-integrations/connectors/source-stripe/source_stripe/__init__.py index 06387f3072c54..a295fa0a39ead 100644 --- a/airbyte-integrations/connectors/source-stripe/source_stripe/__init__.py +++ b/airbyte-integrations/connectors/source-stripe/source_stripe/__init__.py @@ -1,6 +1,7 @@ # -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. # + from .source import SourceStripe __all__ = ["SourceStripe"] diff --git a/airbyte-integrations/connectors/source-stripe/source_stripe/error_handlers/__init__.py b/airbyte-integrations/connectors/source-stripe/source_stripe/error_handlers/__init__.py deleted file mode 100644 index ac7f764fd5a4c..0000000000000 --- a/airbyte-integrations/connectors/source-stripe/source_stripe/error_handlers/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .parent_incremental_stripe_sub_stream_error_handler import ParentIncrementalStripeSubStreamErrorHandler -from .stripe_error_handler import StripeErrorHandler - -__all__ = ["StripeErrorHandler", "ParentIncrementalStripeSubStreamErrorHandler"] diff --git a/airbyte-integrations/connectors/source-stripe/source_stripe/error_handlers/parent_incremental_stripe_sub_stream_error_handler.py b/airbyte-integrations/connectors/source-stripe/source_stripe/error_handlers/parent_incremental_stripe_sub_stream_error_handler.py deleted file mode 100644 index c909371d1ede1..0000000000000 --- a/airbyte-integrations/connectors/source-stripe/source_stripe/error_handlers/parent_incremental_stripe_sub_stream_error_handler.py +++ /dev/null @@ -1,24 +0,0 @@ -# -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -# - -from typing import Optional, Union - -import requests - -from airbyte_cdk.sources.streams.http.error_handlers.response_models import ErrorResolution -from source_stripe.error_handlers.stripe_error_handler import StripeErrorHandler - - -class ParentIncrementalStripeSubStreamErrorHandler(StripeErrorHandler): - def interpret_response(self, response_or_exception: Optional[Union[requests.Response, Exception]] = None) -> ErrorResolution: - if not isinstance(response_or_exception, Exception) and response_or_exception.status_code == requests.codes.not_found: - # When running incremental sync with state, the returned parent object very likely will not contain sub-items - # as the events API does not support expandable items. Parent class will try getting sub-items from this object, - # then from its own API. In case there are no sub-items at all for this entity, API will raise 404 error. - self._logger.warning( - f"Data was not found for URL: {response_or_exception.request.url}. " - "If this is a path for getting child attributes like /v1/checkout/sessions//line_items when running " - "the incremental sync, you may safely ignore this warning." - ) - return super().interpret_response(response_or_exception) diff --git a/airbyte-integrations/connectors/source-stripe/source_stripe/error_handlers/stripe_error_handler.py b/airbyte-integrations/connectors/source-stripe/source_stripe/error_handlers/stripe_error_handler.py deleted file mode 100644 index cc3bce0820be7..0000000000000 --- a/airbyte-integrations/connectors/source-stripe/source_stripe/error_handlers/stripe_error_handler.py +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -# - -import logging -from typing import Optional, Union - -import requests -from requests.exceptions import InvalidURL - -from airbyte_cdk.models import FailureType -from airbyte_cdk.sources.streams.http import HttpStream -from airbyte_cdk.sources.streams.http.error_handlers import HttpStatusErrorHandler -from airbyte_cdk.sources.streams.http.error_handlers.response_models import ErrorResolution, ResponseAction - - -STRIPE_ERROR_CODES = { - "more_permissions_required": "This is most likely due to insufficient permissions on the credentials in use. " - "Try to grant required permissions/scopes or re-authenticate", - "account_invalid": "The card, or account the card is connected to, is invalid. You need to contact your card issuer " - "to check that the card is working correctly.", - "oauth_not_supported": "Please use a different authentication method.", -} - -DOCS_URL = f"https://docs.airbyte.com/integrations/sources/stripe" -DOCUMENTATION_MESSAGE = f"Please visit {DOCS_URL} to learn more. " - - -class StripeErrorHandler(HttpStatusErrorHandler): - def interpret_response(self, response_or_exception: Optional[Union[requests.Response, Exception]] = None) -> ErrorResolution: - if isinstance(response_or_exception, InvalidURL): - return ErrorResolution( - response_action=ResponseAction.RETRY, - failure_type=FailureType.transient_error, - error_message="source-stripe has faced a temporary DNS resolution issue. Retrying...", - ) - if not isinstance(response_or_exception, Exception) and response_or_exception.status_code in ( - requests.codes.bad_request, - requests.codes.forbidden, - ): - parsed_error = response_or_exception.json() - error_code = parsed_error.get("error", {}).get("code") - error_message = STRIPE_ERROR_CODES.get(error_code, parsed_error.get("error", {}).get("message")) - - if error_message: - reason = f"The endpoint {response_or_exception.url} returned {response_or_exception.status_code}: {response_or_exception.reason}. {error_message}. {DOCUMENTATION_MESSAGE} " - response_error_message = HttpStream.parse_response_error_message(response_or_exception) - if response_error_message: - reason += response_error_message - - return ErrorResolution(response_action=ResponseAction.IGNORE, error_message=reason) - return super().interpret_response(response_or_exception) diff --git a/airbyte-integrations/connectors/source-stripe/source_stripe/error_mappings/__init__.py b/airbyte-integrations/connectors/source-stripe/source_stripe/error_mappings/__init__.py deleted file mode 100644 index 973f6adbb2a31..0000000000000 --- a/airbyte-integrations/connectors/source-stripe/source_stripe/error_mappings/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .parent_incremental_stripe_sub_stream_error_mapping import PARENT_INCREMENTAL_STRIPE_SUB_STREAM_ERROR_MAPPING - -__all__ = ["PARENT_INCREMENTAL_STRIPE_SUB_STREAM_ERROR_MAPPING"] diff --git a/airbyte-integrations/connectors/source-stripe/source_stripe/error_mappings/parent_incremental_stripe_sub_stream_error_mapping.py b/airbyte-integrations/connectors/source-stripe/source_stripe/error_mappings/parent_incremental_stripe_sub_stream_error_mapping.py deleted file mode 100644 index 70cb8d1d425e0..0000000000000 --- a/airbyte-integrations/connectors/source-stripe/source_stripe/error_mappings/parent_incremental_stripe_sub_stream_error_mapping.py +++ /dev/null @@ -1,14 +0,0 @@ -# -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. -# - -from airbyte_cdk.sources.streams.http.error_handlers.default_error_mapping import DEFAULT_ERROR_MAPPING -from airbyte_cdk.sources.streams.http.error_handlers.response_models import ErrorResolution, ResponseAction - - -PARENT_INCREMENTAL_STRIPE_SUB_STREAM_ERROR_MAPPING = DEFAULT_ERROR_MAPPING | { - 404: ErrorResolution( - response_action=ResponseAction.IGNORE, - error_message="Data was not found for URL.", - ), -} diff --git a/airbyte-integrations/connectors/source-stripe/source_stripe/manifest.yaml b/airbyte-integrations/connectors/source-stripe/source_stripe/manifest.yaml new file mode 100644 index 0000000000000..4be92a787adcb --- /dev/null +++ b/airbyte-integrations/connectors/source-stripe/source_stripe/manifest.yaml @@ -0,0 +1,1518 @@ +version: 6.33.0 + +type: DeclarativeSource + +check: + type: CheckStream + stream_names: + - accounts + +definitions: + # Base components + base_stream: + type: DeclarativeStream + retriever: + $ref: "#/definitions/base_retriever" + schema_loader: + type: JsonFileSchemaLoader + file_path: "./source_stripe/schemas/{{ parameters['name'] }}.json" + + base_retriever: + type: SimpleRetriever + requester: + $ref: "#/definitions/base_requester" + record_selector: + type: RecordSelector + extractor: + type: DpathExtractor + field_path: + - data + transform_before_filtering: true + schema_normalization: Default + paginator: + $ref: "#/definitions/base_paginator" + + base_requester: + type: HttpRequester + url_base: https://api.stripe.com/v1 + authenticator: + $ref: "#/definitions/bearer_authenticator" + http_method: GET + request_headers: + Stripe-Version: "2022-11-15" + Stripe-Account: '{{ config.get("account_id") }}' + error_handler: + type: CompositeErrorHandler + error_handlers: + - type: DefaultErrorHandler + response_filters: + - type: HttpResponseFilter + action: IGNORE + http_codes: + - 403 + error_message: >- + {{ response['error']['message'] }} + - type: DefaultErrorHandler + response_filters: + - type: HttpResponseFilter + action: IGNORE + http_codes: + - 400 + error_message: >- + {{ response['error']['message'] }} + - type: DefaultErrorHandler + response_filters: + - type: HttpResponseFilter + action: IGNORE + http_codes: + - 404 + error_message: >- + Data was not found. Error message: {{ response['error']['message'] }} If this is a path for getting + child attributes like /v1/checkout/sessions//line_items when running the incremental sync, + you may safely ignore this warning. + bearer_authenticator: + type: BearerAuthenticator + api_token: "{{ config['client_secret'] }}" + + base_paginator: + type: DefaultPaginator + page_token_option: + type: RequestOption + inject_into: request_parameter + field_name: starting_after + page_size_option: + type: RequestOption + field_name: limit + inject_into: request_parameter + pagination_strategy: + type: CursorPagination + page_size: 100 + cursor_value: '{{ response["data"][-1]["id"] }}' + stop_condition: '{{ not response.get("has_more", False) }}' + + base_incremental_sync: + type: DatetimeBasedCursor + cursor_datetime_formats: + - "%s" + datetime_format: "%s" + step: P{{ config.get('slice_range', 365) }}D + cursor_granularity: PT1S + lookback_window: P{{ config.get('lookback_window_days', 0) }}D + start_datetime: + type: MinMaxDatetime + datetime: "{{ format_datetime(config.get('start_date', '2017-01-25T00:00:00Z'), '%Y-%m-%dT%H:%M:%S%z') }}" + datetime_format: "%Y-%m-%dT%H:%M:%S%z" + end_datetime: + type: MinMaxDatetime + datetime: "{{ now_utc().strftime('%Y-%m-%dT%H:%M:%SZ') }}" + datetime_format: "%Y-%m-%dT%H:%M:%SZ" + start_time_option: + type: RequestOption + field_name: "created[gte]" + inject_into: "request_parameter" + end_time_option: + type: RequestOption + field_name: "created[lte]" + inject_into: "request_parameter" + + # Regular flow components + created_stream: + $ref: "#/definitions/base_stream" + primary_key: + - id + incremental_sync: + $ref: "#/definitions/created_incremental_sync" + + created_incremental_sync: + $ref: "#/definitions/base_incremental_sync" + cursor_field: created + + # Entity flow components + entity_stream: + $ref: "#/definitions/base_stream" + primary_key: + - id + incremental_sync: + $ref: "#/definitions/entity_with_slice_cursor" + transformations: + - type: AddFields + fields: + - path: + - updated + value: "{{ record.get('updated', record.get('created', now_utc().timestamp())) | int }}" + value_type: integer + + entity_restricted_stream: + $ref: "#/definitions/base_stream" + primary_key: + - id + incremental_sync: + $ref: "#/definitions/entity_single_slice_cursor" + transformations: + - type: AddFields + fields: + - path: + - updated + value: "{{ record.get('updated', record.get('created', now_utc().timestamp())) | int }}" + value_type: integer + + entity_with_slice_cursor: + type: DatetimeBasedCursor + cursor_field: updated + cursor_datetime_formats: + - "%s" + datetime_format: "%s" + step: P{{ config.get('slice_range', 365) }}D + cursor_granularity: PT1S + lookback_window: P{{ config.get('lookback_window_days', 0) }}D + start_datetime: + type: MinMaxDatetime + datetime: "{{ format_datetime(config.get('start_date', '2017-01-25T00:00:00Z'), '%Y-%m-%dT%H:%M:%S%z') }}" + datetime_format: "%Y-%m-%dT%H:%M:%S%z" + end_datetime: + type: MinMaxDatetime + datetime: "{{ now_utc().strftime('%Y-%m-%dT%H:%M:%SZ') }}" + datetime_format: "%Y-%m-%dT%H:%M:%SZ" + start_time_option: + type: RequestOption + field_name: "created[gte]" + inject_into: "request_parameter" + end_time_option: + type: RequestOption + field_name: "created[lte]" + inject_into: "request_parameter" + + entity_single_slice_cursor: + type: DatetimeBasedCursor + cursor_field: updated + cursor_datetime_formats: + - "%s" + datetime_format: "%s" + lookback_window: P{{ config.get('lookback_window_days', 0) }}D + start_datetime: + type: MinMaxDatetime + datetime: "{{ format_datetime(config.get('start_date', '2017-01-25T00:00:00Z'), '%Y-%m-%dT%H:%M:%S%z') }}" + datetime_format: "%Y-%m-%dT%H:%M:%S%z" + end_datetime: + type: MinMaxDatetime + datetime: "{{ now_utc().strftime('%Y-%m-%dT%H:%M:%SZ') }}" + datetime_format: "%Y-%m-%dT%H:%M:%SZ" + + # Events flow components + events_based_stream: + $ref: "#/definitions/base_stream" + primary_key: + - id + incremental_sync: + $ref: "#/definitions/events_read_slice_cursor" + retriever: + $ref: "#/definitions/events_objects_retriever" + transformations: + - type: AddFields + fields: + - path: + - data + - object + - is_deleted + value: "{{ True }}" + condition: "{{ record.get('data', {}).get('object', False) and record.get('type', '').endswith('.deleted') }}" + - type: AddFields + fields: + - path: + - data + - object + - updated + value: "{{ record.get('updated', record.get('created', now_utc().timestamp())) | int }}" + value_type: integer + condition: "{{ record.get('data', {}).get('object', False) }}" + - type: DpathFlattenFields + field_path: + - data + - object + replace_record: true + + events_objects_retriever: + $ref: "#/definitions/base_retriever" + requester: + $ref: "#/definitions/base_requester" + path: events + + events_read_slice_cursor: + type: DatetimeBasedCursor + cursor_field: updated + cursor_datetime_formats: + - "%s" + datetime_format: "%s" + step: P{{ config.get('slice_range', 365) }}D + cursor_granularity: PT1S + lookback_window: P{{ config.get('lookback_window_days', 0) }}D + start_datetime: + type: MinMaxDatetime + datetime: "{{ format_datetime(config.get('start_date', '2017-01-25T00:00:00Z'), '%Y-%m-%dT%H:%M:%S%z') }}" + datetime_format: "%Y-%m-%dT%H:%M:%S%z" + min_datetime: "{{ (now_utc() - duration('P30D')).strftime('%Y-%m-%dT%H:%M:%SZ') }}" + end_datetime: + type: MinMaxDatetime + datetime: "{{ now_utc().strftime('%Y-%m-%dT%H:%M:%SZ') }}" + datetime_format: "%Y-%m-%dT%H:%M:%SZ" + start_time_option: + type: RequestOption + field_name: "created[gte]" + inject_into: "request_parameter" + end_time_option: + type: RequestOption + field_name: "created[lte]" + inject_into: "request_parameter" + + streams: + events: + $ref: "#/definitions/created_stream" + $parameters: + path: events + name: events + shipping_rates: + $ref: "#/definitions/created_stream" + $parameters: + path: shipping_rates + name: shipping_rates + balance_transactions: + $ref: "#/definitions/created_stream" + $parameters: + path: balance_transactions + name: balance_transactions + files: + $ref: "#/definitions/created_stream" + $parameters: + path: files + name: files + file_links: + $ref: "#/definitions/created_stream" + $parameters: + path: file_links + name: file_links + + customers: + type: StateDelegatingStream + $parameters: + name: customers + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: customers + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["customer.created", "customer.updated", "customer.deleted"]}}' + + subscriptions: + type: StateDelegatingStream + $parameters: + name: subscriptions + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: subscriptions + requester: + $ref: "#/definitions/base_requester" + request_parameters: + status: "all" + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["customer.subscription.created", "customer.subscription.paused", "customer.subscription.pending_update_applied", "customer.subscription.pending_update_expired", "customer.subscription.resumed", "customer.subscription.trial_will_end", "customer.subscription.updated", "customer.subscription.deleted"]}}' + + invoices: + type: StateDelegatingStream + $parameters: + name: invoices + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: invoices + requester: + $ref: "#/definitions/base_requester" + request_parameters: + expand[]: '{{["data.discounts", "data.total_tax_amounts.tax_rate"]}}' + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["invoice.created", "invoice.deleted", "invoice.finalization_failed", "invoice.finalized", "invoice.marked_uncollectible", "invoice.overdue", "invoice.paid", "invoice.payment_action_required", "invoice.payment_failed", "invoice.payment_succeeded", "invoice.sent", "invoice.updated", "invoice.voided", "invoice.will_be_due"]}}' + + transfers: + type: StateDelegatingStream + $parameters: + name: transfers + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: transfers + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["transfer.created", "transfer.reversed", "transfer.updated"]}}' + + refunds: + type: StateDelegatingStream + $parameters: + name: refunds + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: refunds + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["refund.created", "refund.updated", "charge.refund.updated"]}}' + + authorizations: + type: StateDelegatingStream + $parameters: + name: authorizations + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: issuing/authorizations + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["issuing_authorization.created", "issuing_authorization.request", "issuing_authorization.updated"]}}' + + cardholders: + type: StateDelegatingStream + $parameters: + name: cardholders + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: issuing/cardholders + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["issuing_cardholder.created", "issuing_cardholder.updated"]}}' + + charges: + type: StateDelegatingStream + $parameters: + name: charges + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: charges + requester: + $ref: "#/definitions/base_requester" + request_parameters: + expand[]: '{{["data.refunds"]}}' + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["charge.captured", "charge.expired", "charge.failed", "charge.pending", "charge.refunded", "charge.refund.updated", "charge.succeeded", "charge.updated"]}}' + + coupons: + type: StateDelegatingStream + $parameters: + name: coupons + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: coupons + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["coupon.created", "coupon.updated", "coupon.deleted"]}}' + + disputes: + type: StateDelegatingStream + $parameters: + name: disputes + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: disputes + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["charge.dispute.closed", "charge.dispute.created", "charge.dispute.funds_reinstated", "charge.dispute.funds_withdrawn", "charge.dispute.updated"]}}' + + application_fees: + type: StateDelegatingStream + $parameters: + name: application_fees + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: application_fees + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["application_fee.created", "application_fee.refunded"]}}' + + invoice_items: + type: StateDelegatingStream + $parameters: + name: invoice_items + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: invoiceitems + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["invoiceitem.created", "invoiceitem.updated", "invoiceitem.deleted"]}}' + + payouts: + type: StateDelegatingStream + $parameters: + name: payouts + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: payouts + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["payout.canceled", "payout.created", "payout.failed", "payout.paid", "payout.reconciliation_completed", "payout.updated"]}}' + + plans: + type: StateDelegatingStream + $parameters: + name: plans + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: plans + requester: + $ref: "#/definitions/base_requester" + request_parameters: + expand[]: '{{["data.tiers"]}}' + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["plan.created", "plan.updated", "plan.deleted"]}}' + + prices: + type: StateDelegatingStream + $parameters: + name: prices + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: prices + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["price.created", "price.updated", "price.deleted"]}}' + + products: + type: StateDelegatingStream + $parameters: + name: products + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: products + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["product.created", "product.updated", "product.deleted"]}}' + + reviews: + type: StateDelegatingStream + $parameters: + name: reviews + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: reviews + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["review.closed", "review.opened"]}}' + + subscription_schedule: + type: StateDelegatingStream + $parameters: + name: subscription_schedule + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: subscription_schedules + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["subscription_schedule.aborted", "subscription_schedule.canceled", "subscription_schedule.completed", "subscription_schedule.created", "subscription_schedule.expiring", "subscription_schedule.released", "subscription_schedule.updated"]}}' + + payment_intents: + type: StateDelegatingStream + $parameters: + name: payment_intents + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: payment_intents + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["payment_intent.amount_capturable_updated", "payment_intent.canceled", "payment_intent.created", "payment_intent.partially_funded", "payment_intent.payment_failed", "payment_intent.processing", "payment_intent.requires_action", "payment_intent.succeeded"]}}' + + promotion_codes: + type: StateDelegatingStream + $parameters: + name: promotion_codes + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: promotion_codes + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["promotion_code.created", "promotion_code.updated"]}}' + + setup_intents: + type: StateDelegatingStream + $parameters: + name: setup_intents + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: setup_intents + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["setup_intent.canceled", "setup_intent.created", "setup_intent.requires_action", "setup_intent.setup_failed", "setup_intent.succeeded"]}}' + + cards: + type: StateDelegatingStream + $parameters: + name: cards + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: issuing/cards + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["issuing_card.created", "issuing_card.updated"]}}' + + transactions: + type: StateDelegatingStream + $parameters: + name: transactions + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: issuing/transactions + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["issuing_transaction.created", "issuing_transaction.updated"]}}' + + top_ups: + type: StateDelegatingStream + $parameters: + name: top_ups + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: topups + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["topup.canceled", "topup.created", "topup.failed", "topup.reversed", "topup.succeeded"]}}' + + accounts: + type: StateDelegatingStream + $parameters: + name: accounts + full_refresh_stream: + $ref: "#/definitions/entity_restricted_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: accounts + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["account.updated", "account.external_account.created", "account.external_account.updated", "account.external_account.deleted"]}}' + + checkout_sessions: + type: StateDelegatingStream + $parameters: + name: checkout_sessions + full_refresh_stream: + $ref: "#/definitions/entity_restricted_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: checkout/sessions + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["checkout.session.async_payment_failed", "checkout.session.async_payment_succeeded", "checkout.session.completed", "checkout.session.expired"]}}' + + external_account_cards: + type: StateDelegatingStream + $parameters: + name: external_account_cards + full_refresh_stream: + $ref: "#/definitions/entity_restricted_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: accounts/{{ config["account_id"] }}/external_accounts + requester: + $ref: "#/definitions/base_requester" + request_parameters: + object: "card" + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["account.external_account.created", "account.external_account.updated", "account.external_account.deleted"]}}' + record_filter: + condition: "{{ record['object'] == 'card' }}" + + external_account_bank_accounts: + type: StateDelegatingStream + $parameters: + name: external_account_bank_accounts + full_refresh_stream: + $ref: "#/definitions/entity_restricted_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: accounts/{{ config["account_id"] }}/external_accounts + requester: + $ref: "#/definitions/base_requester" + request_parameters: + object: "bank_account" + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["account.external_account.created", "account.external_account.updated", "account.external_account.deleted"]}}' + record_filter: + condition: "{{ record['object'] == 'bank_account' }}" + + credit_notes: + type: StateDelegatingStream + $parameters: + name: credit_notes + full_refresh_stream: + $ref: "#/definitions/entity_restricted_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: credit_notes + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["credit_note.created", "credit_note.updated", "credit_note.voided"]}}' + + early_fraud_warnings: + type: StateDelegatingStream + $parameters: + name: early_fraud_warnings + full_refresh_stream: + $ref: "#/definitions/entity_restricted_stream" + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: radar/early_fraud_warnings + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["radar.early_fraud_warning.created", "radar.early_fraud_warning.updated"]}}' + + customer_balance_transactions: + $ref: "#/definitions/entity_stream" + $parameters: + name: customer_balance_transactions + retriever: + $ref: "#/definitions/base_retriever" + $parameters: + path: customers/{{ stream_partition.customer_id }}/balance_transactions + partition_router: + type: SubstreamPartitionRouter + parent_stream_configs: + - type: ParentStreamConfig + parent_key: id + partition_field: customer_id + stream: + $ref: "#/definitions/streams/customers" + incremental_dependency: true + incremental_sync: + $ref: "#/definitions/entity_single_slice_cursor" + cursor_field: created + transformations: + - type: RemoveFields + field_pointers: + - - updated # Remove filed that added in entity_stream + + payout_balance_transactions: + $ref: "#/definitions/entity_stream" + $parameters: + name: payout_balance_transactions + retriever: + $ref: "#/definitions/base_retriever" + requester: + $ref: "#/definitions/base_requester" + request_parameters: + "payout": "{{ stream_partition.payout_id }}" + partition_router: + type: SubstreamPartitionRouter + parent_stream_configs: + - type: ParentStreamConfig + parent_key: id + partition_field: payout_id + stream: + $ref: "#/definitions/streams/payouts" + incremental_dependency: true + extra_fields: + - ["updated"] + $parameters: + path: balance_transactions + incremental_sync: + $ref: "#/definitions/entity_single_slice_cursor" + cursor_field: updated + transformations: + - type: AddFields + fields: + - path: + - payout + value: "{{ stream_slice['payout_id'] }}" + - path: + - updated + value: "{{ stream_slice.extra_fields['updated'] }}" + value_type: integer + + checkout_sessions_line_items: + $ref: "#/definitions/entity_stream" + $parameters: + name: checkout_sessions_line_items + retriever: + $ref: "#/definitions/base_retriever" + requester: + $ref: "#/definitions/base_requester" + request_parameters: + expand[]: '{{["data.discounts", "data.taxes"]}}' + partition_router: + type: SubstreamPartitionRouter + parent_stream_configs: + - type: ParentStreamConfig + parent_key: id + partition_field: checkout_session_id + stream: + $ref: "#/definitions/streams/checkout_sessions" + incremental_dependency: true + extra_fields: + - ["updated"] + - ["created"] + - ["expires_at"] + $parameters: + path: checkout/sessions/{{ stream_partition.checkout_session_id }}/line_items + incremental_sync: + $ref: "#/definitions/entity_single_slice_cursor" + cursor_field: checkout_session_updated + transformations: + - type: AddFields + fields: + - path: + - checkout_session_id + value: "{{ stream_slice['checkout_session_id']}}" + - path: + - checkout_session_created + value: "{{ stream_slice.extra_fields['created'] | int}}" + - path: + - checkout_session_updated + value: "{{ stream_slice.extra_fields['updated'] | int}}" + - path: + - checkout_session_expires_at + value: "{{ stream_slice.extra_fields['expires_at'] | int}}" + + transfer_reversals: + $ref: "#/definitions/entity_stream" + $parameters: + name: transfer_reversals + retriever: + $ref: "#/definitions/base_retriever" + partition_router: + type: SubstreamPartitionRouter + parent_stream_configs: + - type: ParentStreamConfig + parent_key: id + partition_field: transfer_id + stream: + $ref: "#/definitions/streams/transfers" + incremental_dependency: true + $parameters: + path: transfers/{{ stream_partition.transfer_id }}/reversals + incremental_sync: + $ref: "#/definitions/entity_single_slice_cursor" + cursor_field: created + transformations: + - type: RemoveFields + field_pointers: + - - updated # Remove filed that added in entity_stream + + payment_methods: + type: StateDelegatingStream + $parameters: + name: payment_methods + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + partition_router: + type: SubstreamPartitionRouter + parent_stream_configs: + - type: ParentStreamConfig + parent_key: id + partition_field: customer_id + stream: + $ref: "#/definitions/streams/customers" + $parameters: + path: customers/{{stream_partition.customer_id}}/payment_methods + incremental_sync: + $ref: "#/definitions/entity_single_slice_cursor" + global_substream_cursor: true + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + requester: + $ref: "#/definitions/events_objects_retriever/requester" + request_parameters: "{{ {'type': 'payment_method.*'} }}" + + persons: + type: StateDelegatingStream + $parameters: + name: persons + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + partition_router: + type: SubstreamPartitionRouter + parent_stream_configs: + - type: ParentStreamConfig + parent_key: id + partition_field: account_id + stream: + $ref: "#/definitions/streams/accounts" + $parameters: + path: accounts/{{stream_partition.account_id}}/persons + incremental_sync: + $ref: "#/definitions/entity_single_slice_cursor" + global_substream_cursor: true + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["person.created", "person.updated", "person.deleted"]}}' + + invoice_line_items: + type: StateDelegatingStream + $parameters: + name: invoice_line_items + full_refresh_stream: + type: DeclarativeStream + primary_key: + - id + schema_loader: + type: JsonFileSchemaLoader + file_path: "./source_stripe/schemas/{{ parameters['name'] }}.json" + retriever: + type: SimpleRetriever + requester: + $ref: "#/definitions/base_requester" + path: invoices/{{stream_partition.invoice_id}}/lines + record_selector: + type: RecordSelector + extractor: + type: DpathExtractor + field_path: + - data + transform_before_filtering: true + schema_normalization: Default + paginator: + $ref: "#/definitions/base_paginator" + partition_router: + type: SubstreamPartitionRouter + parent_stream_configs: + - type: ParentStreamConfig + parent_key: id + partition_field: invoice_id + extra_fields: + - ["id"] + - ["created"] + - ["updated"] + lazy_read_pointer: ["lines"] + stream: + $ref: "#/definitions/streams/invoices" + incremental_sync: + $ref: "#/definitions/entity_single_slice_cursor" + cursor_field: invoice_updated + transformations: + - type: AddFields + fields: + - path: + - invoice_id + value: "{{ stream_slice.extra_fields['id']}}" + value_type: integer + - type: AddFields + fields: + - path: + - invoice_created + value: "{{ stream_slice.extra_fields['created'] | int}}" + value_type: integer + - type: AddFields + fields: + - path: + - invoice_updated + value: "{{ stream_slice.extra_fields['updated'] | int}}" + value_type: integer + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["invoice.created", "invoice.deleted", "invoice.updated"]}}' + + application_fees_refunds: + type: StateDelegatingStream + $parameters: + name: application_fees_refunds + full_refresh_stream: + type: DeclarativeStream + primary_key: + - id + schema_loader: + type: JsonFileSchemaLoader + file_path: "./source_stripe/schemas/{{ parameters['name'] }}.json" + retriever: + type: SimpleRetriever + requester: + $ref: "#/definitions/base_requester" + path: application_fees/{{ stream_partition.application_fee_id }}/refunds + record_selector: + type: RecordSelector + extractor: + type: DpathExtractor + field_path: + - data + transform_before_filtering: true + schema_normalization: Default + paginator: + $ref: "#/definitions/base_paginator" + partition_router: + type: SubstreamPartitionRouter + parent_stream_configs: + - type: ParentStreamConfig + parent_key: id + partition_field: application_fee_id + extra_fields: + - ["id"] + lazy_read_pointer: ["refunds"] + stream: + $ref: "#/definitions/streams/application_fees" + incremental_sync: + $ref: "#/definitions/entity_single_slice_cursor" + cursor_field: updated + transformations: + - type: AddFields + fields: + - path: + - updated + value: "{{ record.get('updated', record.get('created', now_utc().timestamp())) | int }}" + value_type: integer + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: "{{ {'type': 'application_fee.refund.updated'} }}" + + subscription_items: + type: StateDelegatingStream + $parameters: + name: subscription_items + full_refresh_stream: + type: DeclarativeStream + primary_key: + - id + schema_loader: + type: JsonFileSchemaLoader + file_path: "./source_stripe/schemas/{{ parameters['name'] }}.json" + retriever: + type: SimpleRetriever + requester: + $ref: "#/definitions/base_requester" + path: subscription_items + request_parameters: + subscription: "{{stream_partition.subscription_id}}" + record_selector: + type: RecordSelector + extractor: + type: DpathExtractor + field_path: + - data + transform_before_filtering: true + schema_normalization: Default + paginator: + $ref: "#/definitions/base_paginator" + partition_router: + type: SubstreamPartitionRouter + parent_stream_configs: + - type: ParentStreamConfig + parent_key: id + partition_field: subscription_id + lazy_read_pointer: ["items"] + extra_fields: + - ["updated"] + stream: + $ref: "#/definitions/streams/subscriptions" + incremental_sync: + $ref: "#/definitions/entity_single_slice_cursor" + cursor_field: subscription_updated + transformations: + - type: AddFields + fields: + - path: + - subscription_updated + value: "{{ stream_slice.extra_fields['updated'] | int}}" + value_type: integer + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["customer.subscription.created", "customer.subscription.updated"]}}' + + bank_accounts: + type: StateDelegatingStream + $parameters: + name: bank_accounts + full_refresh_stream: + type: DeclarativeStream + primary_key: + - id + schema_loader: + type: JsonFileSchemaLoader + file_path: "./source_stripe/schemas/{{ parameters['name'] }}.json" + retriever: + type: SimpleRetriever + requester: + $ref: "#/definitions/base_requester" + path: customers/{{ stream_partition.customer_id }}/bank_accounts + record_selector: + type: RecordSelector + extractor: + type: DpathExtractor + field_path: + - data + record_filter: + condition: "{{ record['object'] == 'bank_account' }}" + transform_before_filtering: true + schema_normalization: Default + paginator: + $ref: "#/definitions/base_paginator" + partition_router: + type: SubstreamPartitionRouter + parent_stream_configs: + - type: ParentStreamConfig + parent_key: id + partition_field: customer_id + extra_fields: + - ["id"] + lazy_read_pointer: ["sources"] + stream: + type: StateDelegatingStream + $parameters: + name: customers + full_refresh_stream: + $ref: "#/definitions/entity_stream" + retriever: + $ref: "#/definitions/base_retriever" + requester: + $ref: "#/definitions/base_requester" + request_parameters: + expand[]: '{{["data.sources"]}}' + $parameters: + path: customers + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["customer.created", "customer.updated", "customer.deleted"]}}' + incremental_sync: + $ref: "#/definitions/entity_single_slice_cursor" + cursor_field: updated + transformations: + - type: AddFields + fields: + - path: + - updated + value: "{{ record.get('updated', record.get('created', now_utc().timestamp())) | int }}" + value_type: integer + incremental_stream: + $ref: "#/definitions/events_based_stream" + retriever: + $ref: "#/definitions/events_objects_retriever" + $parameters: + request_parameters: + types[]: '{{["customer.source.created", "customer.source.expiring", "customer.source.updated", "customer.source.deleted"]}}' + record_filter: + condition: "{{ record['object'] == 'bank_account' }}" + + setup_attempts: + $ref: "#/definitions/created_stream" + $parameters: + path: setup_attempts + name: setup_attempts + retriever: + $ref: "#/definitions/base_retriever" + partition_router: + type: SubstreamPartitionRouter + parent_stream_configs: + - type: ParentStreamConfig + parent_key: id + partition_field: setup_intent_id + stream: + $ref: "#/definitions/streams/setup_intents" + incremental_dependency: true + requester: + $ref: "#/definitions/base_requester" + request_parameters: + setup_intent: "{{ stream_partition.setup_intent_id }}" + incremental_sync: + $ref: "#/definitions/entity_with_slice_cursor" + cursor_field: created + + usage_records: + $ref: "#/definitions/base_stream" + $parameters: + name: usage_records + retriever: + $ref: "#/definitions/base_retriever" + partition_router: + type: SubstreamPartitionRouter + parent_stream_configs: + - type: ParentStreamConfig + parent_key: id + partition_field: subscription_item_id + stream: + $ref: "#/definitions/streams/subscription_items" + requester: + $ref: "#/definitions/base_requester" + path: subscription_items/{{ stream_partition.subscription_item_id }}/usage_record_summaries + +streams: + # These streams are base incremental streams + - $ref: "#/definitions/streams/events" + - $ref: "#/definitions/streams/shipping_rates" + - $ref: "#/definitions/streams/balance_transactions" + - $ref: "#/definitions/streams/files" + - $ref: "#/definitions/streams/file_links" + + ## These streams are state condition streams and have two behaviors depending on whether the state is set: + # - No State: Runs the base stream. + # - State: Uses the event stream to call events related to streams (event types provided by params). + - $ref: "#/definitions/streams/application_fees" + - $ref: "#/definitions/streams/authorizations" + - $ref: "#/definitions/streams/cardholders" + - $ref: "#/definitions/streams/cards" + - $ref: "#/definitions/streams/charges" + - $ref: "#/definitions/streams/coupons" + - $ref: "#/definitions/streams/customers" + - $ref: "#/definitions/streams/disputes" + - $ref: "#/definitions/streams/invoice_items" + - $ref: "#/definitions/streams/invoices" + - $ref: "#/definitions/streams/payment_intents" + - $ref: "#/definitions/streams/payouts" + - $ref: "#/definitions/streams/plans" + - $ref: "#/definitions/streams/prices" + - $ref: "#/definitions/streams/products" + - $ref: "#/definitions/streams/promotion_codes" + - $ref: "#/definitions/streams/refunds" + - $ref: "#/definitions/streams/reviews" + - $ref: "#/definitions/streams/setup_intents" + - $ref: "#/definitions/streams/subscription_schedule" + - $ref: "#/definitions/streams/subscriptions" + - $ref: "#/definitions/streams/top_ups" + - $ref: "#/definitions/streams/transactions" + - $ref: "#/definitions/streams/transfers" + + ## These streams are state condition streams with stricter behavior: + # - No State: Runs the base stream (endpoints strictly define allowed query params and return an error if unexpected params are present). + # - State: Uses the event stream to call events related to streams (event types provided by params). + - $ref: "#/definitions/streams/accounts" + - $ref: "#/definitions/streams/checkout_sessions" + - $ref: "#/definitions/streams/credit_notes" + - $ref: "#/definitions/streams/early_fraud_warnings" + - $ref: "#/definitions/streams/external_account_bank_accounts" + - $ref: "#/definitions/streams/external_account_cards" + + # These streams are base incremental partition streams, with state condition streams as parents: + - $ref: "#/definitions/streams/checkout_sessions_line_items" + - $ref: "#/definitions/streams/customer_balance_transactions" + - $ref: "#/definitions/streams/payout_balance_transactions" + - $ref: "#/definitions/streams/setup_attempts" + - $ref: "#/definitions/streams/transfer_reversals" + + ## These streams are state condition streams with partition behavior: + # - No State: Runs the partition stream that shares the same parent state condition stream. + # - State: Uses the event stream to call events related to streams (event types provided by params). + - $ref: "#/definitions/streams/payment_methods" + - $ref: "#/definitions/streams/persons" + + ## These streams are state condition streams with lazy read logic: + # - No State: Runs lazy read logic where the first N records are fetched from the parent, and pagination continues with the original logic if needed. + # - State: Uses the event stream to call events related to streams (event types provided by params). + - $ref: "#/definitions/streams/application_fees_refunds" + - $ref: "#/definitions/streams/bank_accounts" + - $ref: "#/definitions/streams/invoice_line_items" + - $ref: "#/definitions/streams/subscription_items" + + # These streams are base incremental partition streams with state condition streams as parents using lazy read logic: + - $ref: "#/definitions/streams/usage_records" + +spec: + type: Spec + connection_specification: + $schema: http://json-schema.org/draft-07/schema# + title: Stripe Source Spec + type: object + required: + - client_secret + - account_id + properties: + account_id: + type: string + title: Account ID + description: >- + Your Stripe account ID (starts with 'acct_', find yours here). + order: 0 + client_secret: + type: string + title: Secret Key + description: >- + Stripe API key (usually starts with 'sk_live_'; find yours here). + airbyte_secret: true + order: 1 + start_date: + type: string + title: Replication start date + pattern: ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$ + description: >- + UTC date and time in the format 2017-01-25T00:00:00Z. Only data generated + after this date will be replicated. + default: "2017-01-25T00:00:00Z" + examples: + - "2017-01-25T00:00:00Z" + format: date-time + order: 2 + lookback_window_days: + type: integer + title: Lookback Window in days + default: 0 + minimum: 0 + description: >- + When set, the connector will always re-export data from the past N days, + where N is the value set here. This is useful if your data is frequently updated + after creation. The Lookback Window only applies to streams that do not support event-based incremental syncs: Events, + SetupAttempts, ShippingRates, BalanceTransactions, Files, FileLinks, Refunds. More info here + order: 3 + slice_range: + type: integer + title: Data request time increment in days + 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 + num_workers: + type: integer + title: Number of concurrent workers + minimum: 1 + maximum: 20 + default: 10 + examples: [1, 2, 3] + description: >- + The number of worker thread to use for the sync. + The performance upper boundary depends on call_rate_limit setting and type of account. + order: 5 + call_rate_limit: + type: integer + title: Max number of API calls per second + examples: [25, 100] + description: >- + The number of API calls per second that you allow connector to make. This value can not be bigger than real + API call rate limit (https://stripe.com/docs/rate-limits). If not specified the default maximum is 25 and 100 + calls per second for test and production tokens respectively. + +api_budget: + type: HTTPAPIBudget + policies: + - type: MovingWindowCallRatePolicy + rates: + - limit: 20 + interval: PT1S + matchers: + - method: GET + url_path_pattern: "^/v1/files($|/)" # matches '/files' + - method: GET + url_path_pattern: "^/v1/file_links($|/)" # matches '/file_links' + + - type: MovingWindowCallRatePolicy + rates: + - limit: "{{ 100 if 'sk_test_' in config['client_secret'] else 25 }}" + interval: PT1S + matchers: [] diff --git a/airbyte-integrations/connectors/source-stripe/source_stripe/run.py b/airbyte-integrations/connectors/source-stripe/source_stripe/run.py index e6878a153f191..619d71f1e93b1 100644 --- a/airbyte-integrations/connectors/source-stripe/source_stripe/run.py +++ b/airbyte-integrations/connectors/source-stripe/source_stripe/run.py @@ -1,8 +1,7 @@ # -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. # - import sys import traceback from datetime import datetime diff --git a/airbyte-integrations/connectors/source-stripe/source_stripe/source.py b/airbyte-integrations/connectors/source-stripe/source_stripe/source.py index 7002a36f5a4a7..9c014d0d51ab4 100644 --- a/airbyte-integrations/connectors/source-stripe/source_stripe/source.py +++ b/airbyte-integrations/connectors/source-stripe/source_stripe/source.py @@ -1,660 +1,15 @@ # -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. # -import logging -import os -from datetime import datetime, timedelta, timezone -from typing import Any, List, Mapping, MutableMapping, Optional, Tuple -import pendulum +from typing import Any, Mapping, Optional -from airbyte_cdk.entrypoint import logger as entrypoint_logger from airbyte_cdk.models import ConfiguredAirbyteCatalog, FailureType, SyncMode -from airbyte_cdk.sources.concurrent_source.concurrent_source import ConcurrentSource -from airbyte_cdk.sources.concurrent_source.concurrent_source_adapter import ConcurrentSourceAdapter -from airbyte_cdk.sources.connector_state_manager import ConnectorStateManager -from airbyte_cdk.sources.message.repository import InMemoryMessageRepository +from airbyte_cdk.sources.declarative.yaml_declarative_source import YamlDeclarativeSource from airbyte_cdk.sources.source import TState -from airbyte_cdk.sources.streams import Stream -from airbyte_cdk.sources.streams.call_rate import AbstractAPIBudget, HttpAPIBudget, HttpRequestMatcher, MovingWindowCallRatePolicy, Rate -from airbyte_cdk.sources.streams.concurrent.adapters import StreamFacade -from airbyte_cdk.sources.streams.concurrent.cursor import ConcurrentCursor, CursorField, FinalStateCursor -from airbyte_cdk.sources.streams.concurrent.state_converters.datetime_stream_state_converter import EpochValueConcurrentStreamStateConverter -from airbyte_cdk.sources.streams.http.requests_native_auth import TokenAuthenticator -from airbyte_cdk.utils.traced_exception import AirbyteTracedException -from source_stripe.streams import ( - CreatedCursorIncrementalStripeStream, - Events, - IncrementalStripeStream, - ParentIncrementalStripeSubStream, - SetupAttempts, - StripeLazySubStream, - StripeStream, - StripeSubStream, - UpdatedCursorIncrementalStripeLazySubStream, - UpdatedCursorIncrementalStripeStream, - UpdatedCursorIncrementalStripeSubStream, -) -logger = logging.getLogger("airbyte") - -_MAX_CONCURRENCY = 20 -_DEFAULT_CONCURRENCY = 10 -_CACHE_DISABLED = os.environ.get("CACHE_DISABLED") -USE_CACHE = not _CACHE_DISABLED -STRIPE_TEST_ACCOUNT_PREFIX = "sk_test_" - - -class SourceStripe(ConcurrentSourceAdapter): - message_repository = InMemoryMessageRepository(entrypoint_logger.level) - _SLICE_BOUNDARY_FIELDS_BY_IMPLEMENTATION = { - Events: ("created[gte]", "created[lte]"), - CreatedCursorIncrementalStripeStream: ("created[gte]", "created[lte]"), - } - +class SourceStripe(YamlDeclarativeSource): def __init__(self, catalog: Optional[ConfiguredAirbyteCatalog], config: Optional[Mapping[str, Any]], state: TState, **kwargs): - if config: - concurrency_level = min(config.get("num_workers", _DEFAULT_CONCURRENCY), _MAX_CONCURRENCY) - else: - concurrency_level = _DEFAULT_CONCURRENCY - logger.info(f"Using concurrent cdk with concurrency level {concurrency_level}") - concurrent_source = ConcurrentSource.create( - concurrency_level, concurrency_level // 2, logger, self._slice_logger, self.message_repository - ) - super().__init__(concurrent_source) - self._state = state - if catalog: - self._streams_configured_as_full_refresh = { - configured_stream.stream.name - for configured_stream in catalog.streams - if configured_stream.sync_mode == SyncMode.full_refresh - } - else: - # things will NOT be executed concurrently - self._streams_configured_as_full_refresh = set() - - @staticmethod - def validate_and_fill_with_defaults(config: MutableMapping[str, Any]) -> MutableMapping[str, Any]: - lookback_window_days, slice_range = ( - config.get("lookback_window_days"), - config.get("slice_range"), - ) - if lookback_window_days is None: - config["lookback_window_days"] = 0 - elif not isinstance(lookback_window_days, int) or lookback_window_days < 0: - message = f"Invalid lookback window {lookback_window_days}. Please use only positive integer values or 0." - raise AirbyteTracedException( - message=message, - internal_message=message, - failure_type=FailureType.config_error, - ) - - # verifies the start_date in the config is valid - SourceStripe._start_date_to_timestamp(config) - if slice_range is None: - config["slice_range"] = 365 - elif not isinstance(slice_range, int) or slice_range < 1: - message = f"Invalid slice range value {slice_range}. Please use positive integer values only." - raise AirbyteTracedException( - message=message, - internal_message=message, - failure_type=FailureType.config_error, - ) - return config - - def check_connection(self, logger: logging.Logger, config: MutableMapping[str, Any]) -> Tuple[bool, Any]: - args = self._get_stream_base_args(config) - account_stream = StripeStream(name="accounts", path="accounts", use_cache=USE_CACHE, **args) - try: - next(account_stream.read_records(sync_mode=SyncMode.full_refresh), None) - except AirbyteTracedException as error: - if error.failure_type == FailureType.config_error: - return False, error.message - raise error - return True, None - - def _get_stream_base_args(self, config: MutableMapping[str, Any]) -> MutableMapping[str, Any]: - config = self.validate_and_fill_with_defaults(config) - authenticator = TokenAuthenticator(config["client_secret"]) - start_timestamp = self._start_date_to_timestamp(config) - args = { - "authenticator": authenticator, - "account_id": config["account_id"], - "start_date": start_timestamp, - "slice_range": config["slice_range"], - "api_budget": self.get_api_call_budget(config), - } - return args - - @staticmethod - def customers(**args): - # The Customers stream is instantiated in a dedicated method to allow parametrization and avoid duplicated code. - # It can be used with and without expanded items (as an independent stream or as a parent stream for other streams). - return IncrementalStripeStream( - name="customers", - path="customers", - use_cache=USE_CACHE, - event_types=["customer.created", "customer.updated", "customer.deleted"], - **args, - ) - - @staticmethod - def is_test_account(config: Mapping[str, Any]) -> bool: - """Check if configuration uses Stripe test account (https://stripe.com/docs/keys#obtain-api-keys) - - :param config: - :return: True if configured to use a test account, False - otherwise - """ - - return str(config["client_secret"]).startswith(STRIPE_TEST_ACCOUNT_PREFIX) - - def get_api_call_budget(self, config: Mapping[str, Any]) -> AbstractAPIBudget: - """Get API call budget which connector is allowed to use. - - :param config: - :return: - """ - - max_call_rate = 25 if self.is_test_account(config) else 100 - if config.get("call_rate_limit"): - call_limit = config["call_rate_limit"] - if call_limit > max_call_rate: - logger.warning( - "call_rate_limit is larger than maximum allowed %s, fallback to default %s.", - max_call_rate, - max_call_rate, - ) - call_limit = max_call_rate - else: - call_limit = max_call_rate - - policies = [ - MovingWindowCallRatePolicy( - rates=[Rate(limit=20, interval=timedelta(seconds=1))], - matchers=[ - HttpRequestMatcher(url="https://api.stripe.com/v1/files"), - HttpRequestMatcher(url="https://api.stripe.com/v1/file_links"), - ], - ), - MovingWindowCallRatePolicy( - rates=[Rate(limit=call_limit, interval=timedelta(seconds=1))], - matchers=[], - ), - ] - - return HttpAPIBudget(policies=policies) - - def streams(self, config: MutableMapping[str, Any]) -> List[Stream]: - args = self._get_stream_base_args(config) - incremental_args = {**args, "lookback_window_days": config["lookback_window_days"]} - subscriptions = IncrementalStripeStream( - name="subscriptions", - path="subscriptions", - use_cache=USE_CACHE, - extra_request_params={"status": "all"}, - event_types=[ - "customer.subscription.created", - "customer.subscription.paused", - "customer.subscription.pending_update_applied", - "customer.subscription.pending_update_expired", - "customer.subscription.resumed", - "customer.subscription.trial_will_end", - "customer.subscription.updated", - "customer.subscription.deleted", - ], - **args, - ) - subscription_items = UpdatedCursorIncrementalStripeLazySubStream( - name="subscription_items", - path="subscription_items", - parent=subscriptions, - extra_request_params=lambda self, stream_slice, *args, **kwargs: {"subscription": stream_slice["parent"]["id"]}, - slice_data_retriever=lambda record, stream_slice: { - **record, - "subscription_updated": stream_slice["parent"]["updated"], - }, - cursor_field="subscription_updated", - use_cache=USE_CACHE, - sub_items_attr="items", - event_types=["customer.subscription.created", "customer.subscription.updated"], - **args, - ) - transfers = IncrementalStripeStream( - name="transfers", - path="transfers", - use_cache=USE_CACHE, - event_types=["transfer.created", "transfer.reversed", "transfer.updated"], - **args, - ) - application_fees = IncrementalStripeStream( - name="application_fees", - path="application_fees", - use_cache=USE_CACHE, - event_types=["application_fee.created", "application_fee.refunded"], - **args, - ) - invoices = IncrementalStripeStream( - name="invoices", - path="invoices", - use_cache=USE_CACHE, - expand_items=["data.discounts", "data.total_tax_amounts.tax_rate"], - event_types=[ - "invoice.created", - "invoice.deleted", - "invoice.finalization_failed", - "invoice.finalized", - "invoice.marked_uncollectible", - "invoice.overdue", - "invoice.paid", - "invoice.payment_action_required", - "invoice.payment_failed", - "invoice.payment_succeeded", - "invoice.sent", - "invoice.updated", - "invoice.voided", - "invoice.will_be_due", - # the event type = "invoice.upcoming" doesn't contain the `primary_key = `id` field, - # thus isn't used, see the doc: https://docs.stripe.com/api/invoices/object#invoice_object-id - # reference issue: https://github.com/airbytehq/oncall/issues/5560 - ], - **args, - ) - checkout_sessions = UpdatedCursorIncrementalStripeStream( - name="checkout_sessions", - path="checkout/sessions", - use_cache=USE_CACHE, - legacy_cursor_field="created", - event_types=[ - "checkout.session.async_payment_failed", - "checkout.session.async_payment_succeeded", - "checkout.session.completed", - "checkout.session.expired", - ], - **args, - ) - - payouts = IncrementalStripeStream( - name="payouts", - path="payouts", - event_types=[ - "payout.canceled", - "payout.created", - "payout.failed", - "payout.paid", - "payout.reconciliation_completed", - "payout.updated", - ], - **args, - ) - - streams = [ - checkout_sessions, - Events(**incremental_args), - UpdatedCursorIncrementalStripeStream( - name="external_account_cards", - path=lambda self, *args, **kwargs: f"accounts/{self.account_id}/external_accounts", - event_types=["account.external_account.created", "account.external_account.updated", "account.external_account.deleted"], - legacy_cursor_field=None, - extra_request_params={"object": "card"}, - response_filter=lambda record: record["object"] == "card", - **args, - ), - UpdatedCursorIncrementalStripeStream( - name="external_account_bank_accounts", - path=lambda self, *args, **kwargs: f"accounts/{self.account_id}/external_accounts", - event_types=["account.external_account.created", "account.external_account.updated", "account.external_account.deleted"], - legacy_cursor_field=None, - extra_request_params={"object": "bank_account"}, - response_filter=lambda record: record["object"] == "bank_account", - **args, - ), - UpdatedCursorIncrementalStripeSubStream( - name="persons", - path=lambda self, stream_slice, *args, **kwargs: f"accounts/{stream_slice['parent']['id']}/persons", - parent=StripeStream(name="accounts", path="accounts", use_cache=USE_CACHE, **args), - event_types=["person.created", "person.updated", "person.deleted"], - **args, - ), - SetupAttempts(**incremental_args), - UpdatedCursorIncrementalStripeStream( - name="accounts", - path="accounts", - legacy_cursor_field="created", - event_types=[ - "account.updated", - "account.external_account.created", - "account.external_account.updated", - "account.external_account.deleted", - ], - use_cache=USE_CACHE, - **args, - ), - CreatedCursorIncrementalStripeStream(name="shipping_rates", path="shipping_rates", **incremental_args), - CreatedCursorIncrementalStripeStream(name="balance_transactions", path="balance_transactions", **incremental_args), - CreatedCursorIncrementalStripeStream(name="files", path="files", **incremental_args), - CreatedCursorIncrementalStripeStream(name="file_links", path="file_links", **incremental_args), - IncrementalStripeStream( - name="refunds", - path="refunds", - event_types=[ - "refund.created", - "refund.updated", - # this is the only event that could track the refund updates - "charge.refund.updated", - ], - **args, - ), - UpdatedCursorIncrementalStripeStream( - name="credit_notes", - path="credit_notes", - event_types=["credit_note.created", "credit_note.updated", "credit_note.voided"], - **args, - ), - UpdatedCursorIncrementalStripeStream( - name="early_fraud_warnings", - path="radar/early_fraud_warnings", - event_types=["radar.early_fraud_warning.created", "radar.early_fraud_warning.updated"], - **args, - ), - IncrementalStripeStream( - name="authorizations", - path="issuing/authorizations", - event_types=["issuing_authorization.created", "issuing_authorization.request", "issuing_authorization.updated"], - **args, - ), - self.customers(**args), - IncrementalStripeStream( - name="cardholders", - path="issuing/cardholders", - event_types=["issuing_cardholder.created", "issuing_cardholder.updated"], - **args, - ), - IncrementalStripeStream( - name="charges", - path="charges", - expand_items=["data.refunds"], - event_types=[ - "charge.captured", - "charge.expired", - "charge.failed", - "charge.pending", - "charge.refunded", - "charge.refund.updated", - "charge.succeeded", - "charge.updated", - ], - **args, - ), - IncrementalStripeStream( - name="coupons", path="coupons", event_types=["coupon.created", "coupon.updated", "coupon.deleted"], **args - ), - IncrementalStripeStream( - name="disputes", - path="disputes", - event_types=[ - "charge.dispute.closed", - "charge.dispute.created", - "charge.dispute.funds_reinstated", - "charge.dispute.funds_withdrawn", - "charge.dispute.updated", - ], - **args, - ), - application_fees, - invoices, - IncrementalStripeStream( - name="invoice_items", - path="invoiceitems", - legacy_cursor_field="date", - event_types=[ - "invoiceitem.created", - "invoiceitem.updated", - "invoiceitem.deleted", - ], - **args, - ), - payouts, - ParentIncrementalStripeSubStream( - name="payout_balance_transactions", - path=lambda self, stream_slice, *args, **kwargs: "balance_transactions", - parent=payouts, - cursor_field="updated", - slice_data_retriever=lambda record, stream_slice: { - "payout": stream_slice["parent"]["id"], - "updated": stream_slice["parent"]["updated"], - **record, - }, - extra_request_params=lambda self, stream_slice, *args, **kwargs: {"payout": f"{stream_slice['parent']['id']}"}, - **args, - ), - IncrementalStripeStream( - name="plans", - path="plans", - expand_items=["data.tiers"], - event_types=["plan.created", "plan.updated", "plan.deleted"], - **args, - ), - IncrementalStripeStream(name="prices", path="prices", event_types=["price.created", "price.updated", "price.deleted"], **args), - IncrementalStripeStream( - name="products", path="products", event_types=["product.created", "product.updated", "product.deleted"], **args - ), - IncrementalStripeStream(name="reviews", path="reviews", event_types=["review.closed", "review.opened"], **args), - subscriptions, - IncrementalStripeStream( - name="subscription_schedule", - path="subscription_schedules", - event_types=[ - "subscription_schedule.aborted", - "subscription_schedule.canceled", - "subscription_schedule.completed", - "subscription_schedule.created", - "subscription_schedule.expiring", - "subscription_schedule.released", - "subscription_schedule.updated", - ], - **args, - ), - transfers, - IncrementalStripeStream( - name="payment_intents", - path="payment_intents", - event_types=[ - "payment_intent.amount_capturable_updated", - "payment_intent.canceled", - "payment_intent.created", - "payment_intent.partially_funded", - "payment_intent.payment_failed", - "payment_intent.processing", - "payment_intent.requires_action", - "payment_intent.succeeded", - ], - **args, - ), - IncrementalStripeStream( - name="promotion_codes", - path="promotion_codes", - event_types=["promotion_code.created", "promotion_code.updated"], - **args, - ), - IncrementalStripeStream( - name="setup_intents", - path="setup_intents", - event_types=[ - "setup_intent.canceled", - "setup_intent.created", - "setup_intent.requires_action", - "setup_intent.setup_failed", - "setup_intent.succeeded", - ], - **args, - ), - IncrementalStripeStream( - name="cards", path="issuing/cards", event_types=["issuing_card.created", "issuing_card.updated"], **args - ), - IncrementalStripeStream( - name="transactions", - path="issuing/transactions", - event_types=["issuing_transaction.created", "issuing_transaction.updated"], - **args, - ), - IncrementalStripeStream( - name="top_ups", - path="topups", - event_types=["topup.canceled", "topup.created", "topup.failed", "topup.reversed", "topup.succeeded"], - **args, - ), - ParentIncrementalStripeSubStream( - name="customer_balance_transactions", - path=lambda self, stream_slice, *args, **kwargs: f"customers/{stream_slice['parent']['id']}/balance_transactions", - parent=self.customers(**args), - cursor_field="created", - **args, - ), - UpdatedCursorIncrementalStripeLazySubStream( - name="application_fees_refunds", - path=lambda self, stream_slice, *args, **kwargs: f"application_fees/{stream_slice['parent']['id']}/refunds", - parent=application_fees, - event_types=["application_fee.refund.updated"], - sub_items_attr="refunds", - **args, - ), - UpdatedCursorIncrementalStripeSubStream( - name="payment_methods", - path=lambda self, stream_slice, *args, **kwargs: f"customers/{stream_slice['parent']['id']}/payment_methods", - parent=self.customers(**args), - event_types=["payment_method.*"], - **args, - ), - UpdatedCursorIncrementalStripeLazySubStream( - name="bank_accounts", - path=lambda self, stream_slice, *args, **kwargs: f"customers/{stream_slice['parent']['id']}/bank_accounts", - parent=self.customers(expand_items=["data.sources"], **args), - event_types=["customer.source.created", "customer.source.expiring", "customer.source.updated", "customer.source.deleted"], - legacy_cursor_field=None, - sub_items_attr="sources", - response_filter=lambda record: record["object"] == "bank_account", - **args, - ), - ParentIncrementalStripeSubStream( - name="checkout_sessions_line_items", - path=lambda self, stream_slice, *args, **kwargs: f"checkout/sessions/{stream_slice['parent']['id']}/line_items", - parent=checkout_sessions, - expand_items=["data.discounts", "data.taxes"], - cursor_field="checkout_session_updated", - slice_data_retriever=lambda record, stream_slice: { - "checkout_session_id": stream_slice["parent"]["id"], - "checkout_session_expires_at": stream_slice["parent"]["expires_at"], - "checkout_session_created": stream_slice["parent"]["created"], - "checkout_session_updated": stream_slice["parent"]["updated"], - **record, - }, - **args, - ), - UpdatedCursorIncrementalStripeLazySubStream( - name="invoice_line_items", - path=lambda self, stream_slice, *args, **kwargs: f"invoices/{stream_slice['parent']['id']}/lines", - parent=invoices, - cursor_field="invoice_updated", - event_types=[ - "invoice.created", - "invoice.deleted", - "invoice.updated", - # the event type = "invoice.upcoming" doesn't contain the `primary_key = `id` field, - # thus isn't used, see the doc: https://docs.stripe.com/api/invoices/object#invoice_object-id - # reference issue: https://github.com/airbytehq/oncall/issues/5560 - ], - sub_items_attr="lines", - slice_data_retriever=lambda record, stream_slice: { - "invoice_id": stream_slice["parent"]["id"], - "invoice_created": stream_slice["parent"]["created"], - "invoice_updated": stream_slice["parent"]["updated"], - **record, - }, - **args, - ), - subscription_items, - ParentIncrementalStripeSubStream( - name="transfer_reversals", - path=lambda self, stream_slice, *args, **kwargs: f"transfers/{stream_slice['parent']['id']}/reversals", - parent=transfers, - cursor_field="created", - **args, - ), - StripeSubStream( - name="usage_records", - path=lambda self, - stream_slice, - *args, - **kwargs: f"subscription_items/{stream_slice['parent']['id']}/usage_record_summaries", - parent=subscription_items, - primary_key=None, - **args, - ), - ] - - state_manager = ConnectorStateManager(state=self._state) - return [ - self._to_concurrent( - stream, - datetime.fromtimestamp(self._start_date_to_timestamp(config), timezone.utc), - timedelta(days=config["slice_range"]), - state_manager, - ) - for stream in streams - ] - - def _to_concurrent( - self, stream: Stream, fallback_start: datetime, slice_range: timedelta, state_manager: ConnectorStateManager - ) -> Stream: - if stream.name in self._streams_configured_as_full_refresh: - return StreamFacade.create_from_stream( - stream, - self, - entrypoint_logger, - self._create_empty_state(), - FinalStateCursor(stream_name=stream.name, stream_namespace=stream.namespace, message_repository=self.message_repository), - ) - - state = state_manager.get_stream_state(stream.name, stream.namespace) - slice_boundary_fields = self._SLICE_BOUNDARY_FIELDS_BY_IMPLEMENTATION.get(type(stream)) - if slice_boundary_fields: - cursor_field = CursorField(stream.cursor_field) if isinstance(stream.cursor_field, str) else CursorField(stream.cursor_field[0]) - converter = EpochValueConcurrentStreamStateConverter() - cursor = ConcurrentCursor( - stream.name, - stream.namespace, - state_manager.get_stream_state(stream.name, stream.namespace), - self.message_repository, - state_manager, - converter, - cursor_field, - slice_boundary_fields, - fallback_start, - converter.get_end_provider(), - timedelta(seconds=0), - slice_range, - ) - return StreamFacade.create_from_stream(stream, self, entrypoint_logger, state, cursor) - - return stream - - def _create_empty_state(self) -> MutableMapping[str, Any]: - return {} - - @staticmethod - def _start_date_to_timestamp(config: Mapping[str, Any]) -> int: - if "start_date" not in config: - return pendulum.datetime(2017, 1, 25).int_timestamp # type: ignore # pendulum not typed - - start_date = config["start_date"] - try: - return pendulum.parse(start_date).int_timestamp # type: ignore # pendulum not typed - except pendulum.parsing.exceptions.ParserError as e: - message = f"Invalid start date {start_date}. Please use YYYY-MM-DDTHH:MM:SSZ format." - raise AirbyteTracedException( - message=message, - internal_message=message, - failure_type=FailureType.config_error, - ) from e + super().__init__(catalog=catalog, config=config, state=state, **{"path_to_yaml": "manifest.yaml"}) diff --git a/airbyte-integrations/connectors/source-stripe/source_stripe/spec.yaml b/airbyte-integrations/connectors/source-stripe/source_stripe/spec.yaml deleted file mode 100644 index 719177412a96b..0000000000000 --- a/airbyte-integrations/connectors/source-stripe/source_stripe/spec.yaml +++ /dev/null @@ -1,78 +0,0 @@ -documentationUrl: https://docs.airbyte.com/integrations/sources/stripe -connectionSpecification: - $schema: http://json-schema.org/draft-07/schema# - title: Stripe Source Spec - type: object - required: - - client_secret - - account_id - properties: - account_id: - type: string - title: Account ID - description: >- - Your Stripe account ID (starts with 'acct_', find yours here). - order: 0 - client_secret: - type: string - title: Secret Key - description: >- - Stripe API key (usually starts with 'sk_live_'; find yours here). - airbyte_secret: true - order: 1 - start_date: - type: string - title: Replication start date - pattern: ^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$ - description: >- - UTC date and time in the format 2017-01-25T00:00:00Z. Only data generated - after this date will be replicated. - default: "2017-01-25T00:00:00Z" - examples: - - "2017-01-25T00:00:00Z" - format: date-time - order: 2 - lookback_window_days: - type: integer - title: Lookback Window in days - default: 0 - minimum: 0 - description: >- - When set, the connector will always re-export data from the past N days, - where N is the value set here. This is useful if your data is frequently updated - after creation. The Lookback Window only applies to streams that do not support event-based incremental syncs: Events, - SetupAttempts, ShippingRates, BalanceTransactions, Files, FileLinks, Refunds. More info here - order: 3 - slice_range: - type: integer - title: Data request time increment in days - 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 - num_workers: - type: integer - title: Number of concurrent workers - minimum: 1 - maximum: 20 - default: 10 - examples: [1, 2, 3] - description: >- - The number of worker thread to use for the sync. - The performance upper boundary depends on call_rate_limit setting and type of account. - order: 5 - call_rate_limit: - type: integer - title: Max number of API calls per second - examples: [25, 100] - description: >- - The number of API calls per second that you allow connector to make. This value can not be bigger than real - API call rate limit (https://stripe.com/docs/rate-limits). If not specified the default maximum is 25 and 100 - calls per second for test and production tokens respectively. diff --git a/airbyte-integrations/connectors/source-stripe/source_stripe/streams.py b/airbyte-integrations/connectors/source-stripe/source_stripe/streams.py deleted file mode 100644 index 078ee0a8954f5..0000000000000 --- a/airbyte-integrations/connectors/source-stripe/source_stripe/streams.py +++ /dev/null @@ -1,810 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import copy -import math -import os -from abc import ABC, abstractmethod -from itertools import chain -from typing import Any, Callable, Iterable, List, Mapping, MutableMapping, Optional, Tuple, Union - -import pendulum -import requests - -from airbyte_cdk import BackoffStrategy, StreamSlice -from airbyte_cdk.models import SyncMode -from airbyte_cdk.sources.declarative.requesters.error_handlers.backoff_strategies import ExponentialBackoffStrategy -from airbyte_cdk.sources.streams.checkpoint import Cursor -from airbyte_cdk.sources.streams.checkpoint.resumable_full_refresh_cursor import ResumableFullRefreshCursor -from airbyte_cdk.sources.streams.checkpoint.substream_resumable_full_refresh_cursor import SubstreamResumableFullRefreshCursor -from airbyte_cdk.sources.streams.core import StreamData -from airbyte_cdk.sources.streams.http import HttpStream, HttpSubStream -from airbyte_cdk.sources.streams.http.error_handlers import ErrorHandler -from airbyte_cdk.sources.utils.transform import TransformConfig, TypeTransformer -from source_stripe.error_handlers import ParentIncrementalStripeSubStreamErrorHandler, StripeErrorHandler -from source_stripe.error_mappings import PARENT_INCREMENTAL_STRIPE_SUB_STREAM_ERROR_MAPPING - - -STRIPE_API_VERSION = "2022-11-15" -CACHE_DISABLED = os.environ.get("CACHE_DISABLED") -IS_TESTING = os.environ.get("DEPLOYMENT_MODE") == "testing" -USE_CACHE = not CACHE_DISABLED - - -class IRecordExtractor(ABC): - @abstractmethod - def extract_records(self, records: Iterable[MutableMapping], stream_slice: Optional[Mapping[str, Any]] = None) -> Iterable[Mapping]: - pass - - -class DefaultRecordExtractor(IRecordExtractor): - def __init__(self, response_filter: Optional[Callable] = None, slice_data_retriever: Optional[Callable] = None): - self._response_filter = response_filter or (lambda record: record) - self._slice_data_retriever = slice_data_retriever or (lambda record, *_: record) - - def extract_records( - self, records: Iterable[MutableMapping], stream_slice: Optional[Mapping[str, Any]] = None - ) -> Iterable[MutableMapping]: - yield from filter(self._response_filter, map(lambda x: self._slice_data_retriever(x, stream_slice), records)) - - -class EventRecordExtractor(DefaultRecordExtractor): - def __init__(self, cursor_field: str, response_filter: Optional[Callable] = None, slice_data_retriever: Optional[Callable] = None): - super().__init__(response_filter, slice_data_retriever) - self.cursor_field = cursor_field - - def extract_records( - self, records: Iterable[MutableMapping], stream_slice: Optional[Mapping[str, Any]] = None - ) -> Iterable[MutableMapping]: - for record in records: - item = record["data"]["object"] - item[self.cursor_field] = record["created"] - if record["type"].endswith(".deleted"): - item["is_deleted"] = True - if self._response_filter(item): - yield self._slice_data_retriever(item, stream_slice) - - -class UpdatedCursorIncrementalRecordExtractor(DefaultRecordExtractor): - def __init__( - self, - cursor_field: str, - legacy_cursor_field: Optional[str], - response_filter: Optional[Callable] = None, - slice_data_retriever: Optional[Callable] = None, - ): - super().__init__(response_filter, slice_data_retriever) - self.cursor_field = cursor_field - self.legacy_cursor_field = legacy_cursor_field - - def extract_records( - self, records: Iterable[MutableMapping], stream_slice: Optional[Mapping[str, Any]] = None - ) -> Iterable[MutableMapping]: - records = super().extract_records(records, stream_slice) - for record in records: - if self.cursor_field in record: - yield record - continue # Skip the rest of the loop iteration - # fetch legacy_cursor_field from record; default to current timestamp for initial syncs without an any cursor. - current_cursor_value = record.get(self.legacy_cursor_field, pendulum.now().int_timestamp) - - # yield the record with the added cursor_field - yield record | {self.cursor_field: current_cursor_value} - - -class StripeStream(HttpStream, ABC): - is_resumable = False - url_base = "https://api.stripe.com/v1/" - DEFAULT_SLICE_RANGE = 365 - transformer = TypeTransformer(TransformConfig.DefaultSchemaNormalization) - - def get_error_handler(self) -> Optional[ErrorHandler]: - return StripeErrorHandler(logger=self.logger) - - @property - def primary_key(self) -> Optional[Union[str, List[str], List[List[str]]]]: - return self._primary_key - - @property - def name(self) -> str: - if self._name: - return self._name - return super().name - - def path(self, *args, **kwargs) -> str: - if self._path: - return self._path if isinstance(self._path, str) else self._path(self, *args, **kwargs) - return super().path(*args, **kwargs) - - @property - def use_cache(self) -> bool: - return self._use_cache - - @property - def expand_items(self) -> Optional[List[str]]: - return self._expand_items - - def extra_request_params(self, *args, **kwargs) -> Mapping[str, Any]: - if callable(self._extra_request_params): - return self._extra_request_params(self, *args, **kwargs) - return self._extra_request_params or {} - - def get_backoff_strategy(self) -> Optional[Union[BackoffStrategy, List[BackoffStrategy]]]: - return ExponentialBackoffStrategy(config={}, parameters={}, factor=1) - - @property - def record_extractor(self) -> IRecordExtractor: - return self._record_extractor - - def __init__( - self, - start_date: int, - account_id: str, - *args, - slice_range: int = DEFAULT_SLICE_RANGE, - record_extractor: Optional[IRecordExtractor] = None, - name: Optional[str] = None, - path: Optional[Union[Callable, str]] = None, - use_cache: bool = False, - expand_items: Optional[List[str]] = None, - extra_request_params: Optional[Union[Mapping[str, Any], Callable]] = None, - response_filter: Optional[Callable] = None, - slice_data_retriever: Optional[Callable] = None, - primary_key: Optional[str] = "id", - **kwargs, - ): - self.account_id = account_id - self.start_date = start_date - self.slice_range = slice_range or self.DEFAULT_SLICE_RANGE - self._record_extractor = record_extractor or DefaultRecordExtractor(response_filter, slice_data_retriever) - self._name = name - self._path = path - self._use_cache = use_cache - self._expand_items = expand_items - self._extra_request_params = extra_request_params - self._primary_key = primary_key - super().__init__(*args, **kwargs) - - def next_page_token(self, response: requests.Response) -> Optional[Mapping[str, Any]]: - decoded_response = response.json() - if "has_more" in decoded_response and decoded_response["has_more"] and decoded_response.get("data", []): - last_object_id = decoded_response["data"][-1]["id"] - return {"starting_after": last_object_id} - - 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]: - # Stripe default pagination is 10, max is 100 - params = { - "limit": 100, - **self.extra_request_params(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token), - } - if self.expand_items: - params["expand[]"] = self.expand_items - # Handle pagination by inserting the next page's token in the request parameters - if next_page_token: - params.update(next_page_token) - - return params - - def parse_response( - self, - response: requests.Response, - *, - stream_state: Mapping[str, Any], - stream_slice: Optional[Mapping[str, Any]] = None, - next_page_token: Optional[Mapping[str, Any]] = None, - ) -> Iterable[Mapping[str, Any]]: - yield from self.record_extractor.extract_records(response.json().get("data", []), stream_slice) - - def request_headers(self, **kwargs) -> Mapping[str, Any]: - headers = {"Stripe-Version": STRIPE_API_VERSION} - if self.account_id: - headers["Stripe-Account"] = self.account_id - return headers - - def retry_factor(self) -> float: - """ - Override for testing purposes - """ - return 0 if IS_TESTING else super(StripeStream, self).retry_factor - - def get_cursor(self) -> Optional[Cursor]: - """ - RFR is breaking the pagination in Stripe today. The stream is instantiated using the stream facade here. During the read, this goes - through the concurrent code here so that we can read full refresh streams concurrently. - - However, as there are no cursors and the read records is the one from the HttpStream, we end up assigning the - ResumableFullRefresCursor and hence only read a single page. - - In order to avoid that, we will assume there are no cursor if the cursor if RFR. - """ - parent_cursor = super().get_cursor() - if isinstance(parent_cursor, (ResumableFullRefreshCursor, SubstreamResumableFullRefreshCursor)): - return None - return parent_cursor - - -class IStreamSelector(ABC): - @abstractmethod - def get_parent_stream(self, stream_state: Mapping[str, Any]) -> StripeStream: - pass - - -class CreatedCursorIncrementalStripeStream(StripeStream): - is_resumable = True - # Stripe returns most recently created objects first, so we don't want to persist state until the entire stream has been read - state_checkpoint_interval = math.inf - - @property - def cursor_field(self) -> str: - return self._cursor_field - - def __init__( - self, - *args, - lookback_window_days: int = 0, - start_date_max_days_from_now: Optional[int] = None, - cursor_field: str = "created", - **kwargs, - ): - self._cursor_field = cursor_field - super().__init__(*args, **kwargs) - self.lookback_window_days = lookback_window_days - self.start_date_max_days_from_now = start_date_max_days_from_now - - def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: - """ - Return the latest state by comparing the cursor value in the latest record with the stream's most recent state object - and returning an updated state object. - """ - state_cursor_value = current_stream_state.get(self.cursor_field, 0) - latest_record_value = latest_record.get(self.cursor_field) - if state_cursor_value: - return {self.cursor_field: max(latest_record_value, state_cursor_value)} - return {self.cursor_field: latest_record_value} - - def request_params( - self, - stream_state: Mapping[str, Any] = None, - stream_slice: Mapping[str, Any] = None, - next_page_token: Mapping[str, Any] = None, - ) -> MutableMapping[str, Any]: - params = super(CreatedCursorIncrementalStripeStream, self).request_params(stream_state, stream_slice, next_page_token) - return {"created[gte]": stream_slice["created[gte]"], "created[lte]": stream_slice["created[lte]"], **params} - - 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]]]: - stream_state = stream_state or {} - start_ts = self.get_start_timestamp(stream_state) - if start_ts >= pendulum.now().int_timestamp: - return [] - for start, end in self.chunk_dates(start_ts): - yield StreamSlice(partition={}, cursor_slice={"created[gte]": start, "created[lte]": end}) - - def get_start_timestamp(self, stream_state) -> int: - start_point = self.start_date - # we use +1 second because date range is inclusive - start_point = max(start_point, stream_state.get(self.cursor_field, 0) + 1) - - if start_point and self.lookback_window_days: - self.logger.info(f"Applying lookback window of {self.lookback_window_days} days to stream {self.name}") - start_point = int(pendulum.from_timestamp(start_point).subtract(days=abs(self.lookback_window_days)).timestamp()) - - if self.start_date_max_days_from_now: - allowed_start_date = pendulum.now().subtract(days=self.start_date_max_days_from_now).int_timestamp - if start_point < allowed_start_date: - self.logger.info( - f"Applying the restriction of maximum {self.start_date_max_days_from_now} days lookback to stream {self.name}" - ) - start_point = allowed_start_date - return start_point - - -class Events(CreatedCursorIncrementalStripeStream): - """ - API docs: https://stripe.com/docs/api/events/list - """ - - def __init__(self, *args, event_types: Optional[Iterable[str]] = None, **kwargs): - super().__init__(*args, **kwargs) - self.event_types = event_types - - def request_params( - self, - stream_state: Mapping[str, Any] = None, - 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) - if self.event_types: - if len(self.event_types) > 1: - params["types[]"] = self.event_types - else: - params["type"] = self.event_types - return params - - def path(self, **kwargs): - return "events" - - -class UpdatedCursorIncrementalStripeStream(StripeStream): - is_resumable = True - """ - `CreatedCursorIncrementalStripeStream` does not provide a way to read updated data since given date because the API does not allow to do this. - It only returns newly created entities since given date. So to have all the updated data as well we need to make use of the Events API, - which allows to retrieve updated data since given date for a number of predefined events which are associated with the corresponding - entities. - """ - - @property - def cursor_field(self): - return self._cursor_field - - @property - def legacy_cursor_field(self): - return self._legacy_cursor_field - - @property - def event_types(self) -> Iterable[str]: - """A list of event types that are associated with entity.""" - return self._event_types - - def __init__( - self, - *args, - cursor_field: str = "updated", - legacy_cursor_field: Optional[str] = "created", - event_types: Optional[List[str]] = None, - record_extractor: Optional[IRecordExtractor] = None, - response_filter: Optional[Callable] = None, - **kwargs, - ): - self._event_types = event_types - self._cursor_field = cursor_field - self._legacy_cursor_field = legacy_cursor_field - record_extractor = record_extractor or UpdatedCursorIncrementalRecordExtractor( - self.cursor_field, self.legacy_cursor_field, response_filter - ) - super().__init__(*args, record_extractor=record_extractor, **kwargs) - # `lookback_window_days` is hardcoded as it does not make any sense to re-export events, - # as each event holds the latest value of a record. - # `start_date_max_days_from_now` represents the events API limitation. - self.events_stream = Events( - authenticator=kwargs.get("authenticator"), - lookback_window_days=0, - start_date_max_days_from_now=30, - account_id=self.account_id, - start_date=self.start_date, - slice_range=self.slice_range, - event_types=self.event_types, - cursor_field=self.cursor_field, - record_extractor=EventRecordExtractor(cursor_field=self.cursor_field, response_filter=response_filter), - ) - - def update_cursor_field(self, stream_state: MutableMapping[str, Any]) -> MutableMapping[str, Any]: - if not self.legacy_cursor_field: - # Streams that used to support only full_refresh mode. - # Now they support event-based incremental syncs but have a cursor field only in that mode. - return stream_state - # support for both legacy and new cursor fields - current_stream_state_value = stream_state.get(self.cursor_field, stream_state.get(self.legacy_cursor_field, 0)) - return {self.cursor_field: current_stream_state_value} - - def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: - latest_record_value = latest_record.get(self.cursor_field) - current_stream_state = self.update_cursor_field(current_stream_state) - current_state_value = current_stream_state.get(self.cursor_field) - if current_state_value: - return {self.cursor_field: max(latest_record_value, current_state_value)} - return {self.cursor_field: latest_record_value} - - def stream_slices( - self, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None - ) -> Iterable[Optional[Mapping[str, Any]]]: - # When reading from a stream, a `read_records` is called once per slice. - # We yield a single slice here because we don't want to make duplicate calls for event based incremental syncs. - yield StreamSlice(partition={}, cursor_slice={}) - - def read_event_increments( - self, cursor_field: Optional[List[str]] = None, stream_state: Optional[Mapping[str, Any]] = None - ) -> Iterable[StreamData]: - stream_state = self.update_cursor_field(stream_state or {}) - for event_slice in self.events_stream.stream_slices( - sync_mode=SyncMode.incremental, cursor_field=cursor_field, stream_state=stream_state - ): - yield from self.events_stream.read_records( - SyncMode.incremental, cursor_field=cursor_field, stream_slice=event_slice, stream_state=stream_state - ) - - def read_records( - self, - sync_mode: SyncMode, - cursor_field: Optional[List[str]] = None, - stream_slice: Optional[Mapping[str, Any]] = None, - stream_state: Optional[Mapping[str, Any]] = None, - ) -> Iterable[StreamData]: - if not stream_state: - # both full refresh and initial incremental sync should use usual endpoints - yield from super().read_records(sync_mode, cursor_field=cursor_field, stream_slice=stream_slice, stream_state=stream_state) - return - yield from self.read_event_increments(cursor_field=cursor_field, stream_state=stream_state) - - -class IncrementalStripeStreamSelector(IStreamSelector): - def __init__( - self, - created_cursor_incremental_stream: CreatedCursorIncrementalStripeStream, - updated_cursor_incremental_stream: UpdatedCursorIncrementalStripeStream, - ): - self._created_cursor_stream = created_cursor_incremental_stream - self._updated_cursor_stream = updated_cursor_incremental_stream - - def get_parent_stream(self, stream_state: Mapping[str, Any]) -> StripeStream: - return self._updated_cursor_stream if stream_state else self._created_cursor_stream - - -class IncrementalStripeStream(StripeStream): - is_resumable = True - """ - This class combines both normal incremental sync and event based sync. It uses common endpoints for sliced data syncs in - the full refresh sync mode and initial incremental sync. For incremental syncs with a state, event based sync comes into action. - """ - - def __init__( - self, - *args, - cursor_field: str = "updated", - legacy_cursor_field: Optional[str] = "created", - event_types: Optional[List[str]] = None, - **kwargs, - ): - self._cursor_field = cursor_field - super().__init__(*args, **kwargs) - created_cursor_stream = CreatedCursorIncrementalStripeStream( - *args, - cursor_field=cursor_field, - # `lookback_window_days` set to 0 because this particular instance is in charge of full_refresh/initial incremental syncs only - lookback_window_days=0, - record_extractor=UpdatedCursorIncrementalRecordExtractor(cursor_field, legacy_cursor_field), - **kwargs, - ) - updated_cursor_stream = UpdatedCursorIncrementalStripeStream( - *args, - cursor_field=cursor_field, - legacy_cursor_field=legacy_cursor_field, - event_types=event_types, - **kwargs, - ) - self._parent_stream = None - self.stream_selector = IncrementalStripeStreamSelector(created_cursor_stream, updated_cursor_stream) - - @property - def parent_stream(self): - return self._parent_stream - - @parent_stream.setter - def parent_stream(self, stream): - self._parent_stream = stream - - @property - def cursor_field(self) -> Union[str, List[str]]: - return self._cursor_field - - def stream_slices( - self, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None - ) -> Iterable[Optional[Mapping[str, Any]]]: - self.parent_stream = self.stream_selector.get_parent_stream(stream_state) - yield from self.parent_stream.stream_slices(sync_mode, cursor_field, stream_state) - - def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: - return self.parent_stream.get_updated_state(current_stream_state, latest_record) - - def read_records( - self, - sync_mode: SyncMode, - cursor_field: Optional[List[str]] = None, - stream_slice: Optional[Mapping[str, Any]] = None, - stream_state: Optional[Mapping[str, Any]] = None, - ) -> Iterable[StreamData]: - yield from self.parent_stream.read_records(sync_mode, cursor_field, stream_slice, stream_state) - - -class SetupAttempts(CreatedCursorIncrementalStripeStream, HttpSubStream): - """ - Docs: https://stripe.com/docs/api/setup_attempts/list - """ - - def __init__(self, **kwargs): - # SetupAttempts needs lookback_window, but it's parent class does not - parent_kwargs = copy.copy(kwargs) - parent_kwargs.pop("lookback_window_days") - parent = IncrementalStripeStream( - name="setup_intents", - path="setup_intents", - event_types=[ - "setup_intent.canceled", - "setup_intent.created", - "setup_intent.requires_action", - "setup_intent.setup_failed", - "setup_intent.succeeded", - ], - **parent_kwargs, - ) - super().__init__(parent=parent, **kwargs) - - def path(self, **kwargs) -> str: - return "setup_attempts" - - def stream_slices( - self, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None - ) -> Iterable[Optional[Mapping[str, Any]]]: - # this is a unique combination of CreatedCursorIncrementalStripeStream and HttpSubStream, - # so we need to have all the parent IDs multiplied by all the date slices - incremental_slices = list( - CreatedCursorIncrementalStripeStream.stream_slices( - self, sync_mode=sync_mode, cursor_field=cursor_field, stream_state=stream_state - ) - ) - if incremental_slices: - parent_records = HttpSubStream.stream_slices(self, sync_mode=sync_mode, cursor_field=cursor_field, stream_state=stream_state) - yield from ( - StreamSlice(partition=parent_record, cursor_slice=_slice) - for parent_record in parent_records - for _slice in incremental_slices - ) - else: - yield from [] - - 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]: - setup_intent_id = stream_slice.get("parent", {}).get("id") - params = super().request_params(stream_state=stream_state, stream_slice=stream_slice, next_page_token=next_page_token) - params.update(setup_intent=setup_intent_id) - return params - - -class StripeSubStream(StripeStream, HttpSubStream): - pass - - -class StripeLazySubStream(StripeStream, HttpSubStream): - """ - 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 - all item in parent stream, since parent stream returns 100 items per request. - Note, in major cases, pagination requests are not performed because sub items are fully reported in parent streams - - For example: - Line items are part of each 'invoice' record, so use Invoices stream because - it allows bulk extraction: - 0.1.28 and below - 1 request extracts line items for 1 invoice (+ pagination reqs) - 0.1.29 and above - 1 request extracts line items for 100 invoices (+ pagination reqs) - - if line items object has indication for next pages ('has_more' attr) - then use current stream to extract next pages. In major cases pagination requests - are not performed because line items are fully reported in 'invoice' record - - Example for InvoiceLineItems and parent Invoice streams, record from Invoice stream: - { - "created": 1641038947, <--- 'Invoice' record - "customer": "cus_HezytZRkaQJC8W", - "id": "in_1KD6OVIEn5WyEQxn9xuASHsD", <---- value for 'parent_id' attribute - "object": "invoice", - "total": 0, - ... - "lines": { <---- sub_items_attr - "data": [ - { - "id": "il_1KD6OVIEn5WyEQxnm5bzJzuA", <---- 'Invoice' line item record - "object": "line_item", - ... - }, - {...} - ], - "has_more": false, <---- next pages from 'InvoiceLineItemsPaginated' stream - "object": "list", - "total_count": 2, - "url": "/v1/invoices/in_1KD6OVIEn5WyEQxn9xuASHsD/lines" - } - } - """ - - @property - def sub_items_attr(self) -> str: - """ - :return: string if single primary key, list of strings if composite primary key, list of list of strings if composite primary key consisting of nested fields. - If the stream has no primary keys, return None. - """ - return self._sub_items_attr - - def __init__( - self, - *args, - sub_items_attr: Optional[str] = None, - **kwargs, - ): - super().__init__(*args, **kwargs) - self._sub_items_attr = sub_items_attr - - def request_params(self, stream_slice: Mapping[str, Any] = None, **kwargs): - params = super().request_params(stream_slice=stream_slice, **kwargs) - - # add 'starting_after' param - if not params.get("starting_after") and stream_slice and stream_slice.get("starting_after"): - params["starting_after"] = stream_slice["starting_after"] - - return params - - def read_records(self, sync_mode: SyncMode, stream_slice: Optional[Mapping[str, Any]] = None, **kwargs) -> Iterable[Mapping[str, Any]]: - items_obj = stream_slice["parent"].get(self.sub_items_attr, {}) - if not items_obj: - return - - items_next_pages = [] - items = list(self.record_extractor.extract_records(items_obj.get("data", []), stream_slice)) - if items_obj.get("has_more") and items: - stream_slice = {"starting_after": items[-1]["id"], **stream_slice} - items_next_pages = super().read_records(sync_mode=SyncMode.full_refresh, stream_slice=stream_slice, **kwargs) - yield from chain(items, items_next_pages) - - -class IncrementalStripeLazySubStreamSelector(IStreamSelector): - def __init__(self, updated_cursor_incremental_stream: UpdatedCursorIncrementalStripeStream, lazy_sub_stream: StripeLazySubStream): - self._updated_incremental_stream = updated_cursor_incremental_stream - self._lazy_sub_stream = lazy_sub_stream - - def get_parent_stream(self, stream_state: Mapping[str, Any]) -> StripeStream: - return self._updated_incremental_stream if stream_state else self._lazy_sub_stream - - -class UpdatedCursorIncrementalStripeLazySubStream(StripeStream, ABC): - is_resumable = True - """ - This stream uses StripeLazySubStream under the hood to run full refresh or initial incremental syncs. - In case of subsequent incremental syncs, it uses the UpdatedCursorIncrementalStripeStream class. - """ - - def __init__( - self, - parent: StripeStream, - *args, - cursor_field: str = "updated", - legacy_cursor_field: Optional[str] = "created", - event_types: Optional[List[str]] = None, - sub_items_attr: Optional[str] = None, - response_filter: Optional[Callable] = None, - **kwargs, - ): - self._cursor_field = cursor_field - super().__init__(*args, **kwargs) - self.updated_cursor_incremental_stream = UpdatedCursorIncrementalStripeStream( - *args, - cursor_field=cursor_field, - legacy_cursor_field=legacy_cursor_field, - event_types=event_types, - response_filter=response_filter, - **kwargs, - ) - self.lazy_substream = StripeLazySubStream( - *args, - parent=parent, - sub_items_attr=sub_items_attr, - record_extractor=UpdatedCursorIncrementalRecordExtractor( - cursor_field=cursor_field, - legacy_cursor_field=legacy_cursor_field, - response_filter=response_filter, - slice_data_retriever=kwargs.get("slice_data_retriever"), - ), - **kwargs, - ) - self._parent_stream = None - self.stream_selector = IncrementalStripeLazySubStreamSelector(self.updated_cursor_incremental_stream, self.lazy_substream) - - @property - def cursor_field(self) -> Union[str, List[str]]: - return self._cursor_field - - @property - def parent_stream(self): - return self._parent_stream - - @parent_stream.setter - def parent_stream(self, stream): - self._parent_stream = stream - - def stream_slices( - self, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None - ) -> Iterable[Optional[Mapping[str, Any]]]: - self.parent_stream = self.stream_selector.get_parent_stream(stream_state) - yield from self.parent_stream.stream_slices(sync_mode, cursor_field=cursor_field, stream_state=stream_state) - - def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: - # important note: do not call self.parent_stream here as one of the parents does not have the needed method implemented - return self.updated_cursor_incremental_stream.get_updated_state(current_stream_state, latest_record) - - def read_records( - self, - sync_mode: SyncMode, - cursor_field: Optional[List[str]] = None, - stream_slice: Optional[Mapping[str, Any]] = None, - stream_state: Optional[Mapping[str, Any]] = None, - ) -> Iterable[StreamData]: - yield from self.parent_stream.read_records( - sync_mode, cursor_field=cursor_field, stream_slice=stream_slice, stream_state=stream_state - ) - - -class ParentIncrementalStripeSubStream(StripeSubStream): - is_resumable = True - """ - This stream differs from others in that it runs parent stream in exactly same sync mode it is run itself to generate stream slices. - It also uses regular /v1 API endpoints to sync data no matter what the sync mode is. This means that the event-based API can only - be utilized by the parent stream. - """ - - @property - def cursor_field(self) -> str: - return self._cursor_field - - def __init__(self, cursor_field: str, *args, **kwargs): - self._cursor_field = cursor_field - super().__init__(*args, **kwargs) - - def stream_slices( - self, sync_mode: SyncMode, cursor_field: Optional[List[str]] = None, stream_state: Optional[Mapping[str, Any]] = None - ) -> Iterable[Optional[Mapping[str, Any]]]: - stream_state = stream_state or {} - if stream_state: - # state is shared between self and parent, but cursor fields are different - stream_state = {self.parent.cursor_field: stream_state.get(self.cursor_field, 0)} - parent_stream_slices = self.parent.stream_slices(sync_mode=sync_mode, cursor_field=cursor_field, stream_state=stream_state) - for stream_slice in parent_stream_slices: - parent_records = self.parent.read_records( - sync_mode=sync_mode, cursor_field=cursor_field, stream_slice=stream_slice, stream_state=stream_state - ) - for record in parent_records: - yield StreamSlice(partition={"parent": record}, cursor_slice={}) - - def get_updated_state(self, current_stream_state: MutableMapping[str, Any], latest_record: Mapping[str, Any]) -> Mapping[str, Any]: - return {self.cursor_field: max(current_stream_state.get(self.cursor_field, 0), latest_record[self.cursor_field])} - - def get_error_handler(self) -> Optional[ErrorHandler]: - return ParentIncrementalStripeSubStreamErrorHandler( - logger=self.logger, error_mapping=PARENT_INCREMENTAL_STRIPE_SUB_STREAM_ERROR_MAPPING - ) - - -class UpdatedCursorIncrementalStripeSubStream(UpdatedCursorIncrementalStripeStream, HttpSubStream): - """ - This class behaves exactly the same as its parent, UpdatedCursorIncrementalStripeStream, but the initial/full refresh sync is performed using the parent stream. - """ - - def stream_slices( - self, sync_mode: SyncMode, cursor_field: List[str] = None, stream_state: Mapping[str, Any] = None - ) -> Iterable[Optional[Mapping[str, Any]]]: - if not stream_state: - yield from map( - lambda stream_slice: StreamSlice(partition=stream_slice, cursor_slice={}), - HttpSubStream.stream_slices(self, sync_mode, cursor_field, stream_state), - ) - else: - yield from UpdatedCursorIncrementalStripeStream.stream_slices(self, sync_mode, cursor_field, stream_state) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/conftest.py b/airbyte-integrations/connectors/source-stripe/unit_tests/conftest.py deleted file mode 100644 index da3a15fd2e0fc..0000000000000 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/conftest.py +++ /dev/null @@ -1,62 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -import os - -import pytest - -from airbyte_cdk.sources.streams.concurrent.adapters import StreamFacade -from airbyte_cdk.sources.streams.http.requests_native_auth import TokenAuthenticator -from airbyte_cdk.test.state_builder import StateBuilder - - -os.environ["CACHE_DISABLED"] = "true" -os.environ["DEPLOYMENT_MODE"] = "testing" - - -def pytest_collection_modifyitems(items): - for item in items: - item.add_marker(pytest.mark.timeout(20)) - - -@pytest.fixture(name="config") -def config_fixture(): - config = {"client_secret": "sk_test(live)_", "account_id": "", "start_date": "2020-05-01T00:00:00Z"} - return config - - -@pytest.fixture(name="stream_args") -def stream_args_fixture(): - authenticator = TokenAuthenticator("sk_test(live)_") - args = { - "authenticator": authenticator, - "account_id": "", - "start_date": 1588315041, - "slice_range": 365, - } - return args - - -@pytest.fixture(name="incremental_stream_args") -def incremental_args_fixture(stream_args): - return {"lookback_window_days": 14, **stream_args} - - -@pytest.fixture() -def stream_by_name(config): - # use local import in favour of global because we need to make imports after setting the env variables - from source_stripe.source import SourceStripe - - def mocker(stream_name, source_config=config): - source = SourceStripe(None, source_config, StateBuilder().build()) - streams = source.streams(source_config) - for stream in streams: - if stream.name == stream_name: - if isinstance(stream, StreamFacade): - # to avoid breaking changes for tests, we will return the legacy test. Tests that would be affected by not having this - # would probably need to be moved to integration tests or unit tests - return stream._legacy_stream - return stream - - return mocker diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/config.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/config.py index 9f031974d93bf..0f22127584860 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/config.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/config.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime from typing import Any, Dict diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/helpers.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/helpers.py index 4f95359a8ebfe..0ce314168ab6f 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/helpers.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/helpers.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2024 Airbyte, Inc., all rights reserved. +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. # from typing import Optional diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/pagination.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/pagination.py index acfe9a6132711..1af71bd025e2f 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/pagination.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/pagination.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from typing import Any, Dict diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/request_builder.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/request_builder.py index 51f40323e740e..5d9e57335a798 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/request_builder.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/request_builder.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime from typing import List, Optional diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/response_builder.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/response_builder.py index 7495bffeb4a9e..451a83f8e9b84 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/response_builder.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/response_builder.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# import json diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_accounts.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_accounts.py index ce2e72a67d483..d9075ca399b0d 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_accounts.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_accounts.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime, timedelta, timezone from unittest import TestCase @@ -28,10 +30,7 @@ _ACCOUNT_ID = "acct_1G9HZLIEn49ers" _CLIENT_SECRET = "ConfigBuilder default client secret" _NOW = datetime.now(timezone.utc) -_CONFIG = { - "client_secret": _CLIENT_SECRET, - "account_id": _ACCOUNT_ID, -} +_CONFIG = {"client_secret": _CLIENT_SECRET, "account_id": _ACCOUNT_ID} _NO_STATE = StateBuilder().build() _AVOIDING_INCLUSIVE_BOUNDARIES = timedelta(seconds=1) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_application_fees.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_application_fees.py index dd7a36ebd56a1..ed18c5496b878 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_application_fees.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_application_fees.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime, timedelta, timezone from typing import Any, Dict, List, Optional @@ -164,13 +166,13 @@ def test_given_slice_range_when_read_then_perform_multiple_requests(self, http_m slice_datetime = start_date + slice_range http_mocker.get( - _application_fees_request().with_created_gte(start_date).with_created_lte(slice_datetime).with_limit(100).build(), + _application_fees_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).build(), _application_fees_response().build(), ) http_mocker.get( _application_fees_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) + .with_created_gte(start_date) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .build(), _application_fees_response().build(), @@ -178,10 +180,8 @@ def test_given_slice_range_when_read_then_perform_multiple_requests(self, http_m self._read(_config().with_start_date(start_date).with_slice_range_in_days(slice_range.days)) - # request matched http_mocker - @HttpMocker() - def test_given_http_status_400_when_read_then_stream_did_not_run(self, http_mocker: HttpMocker) -> None: + def test_given_http_status_400_when_read_then_stream_incomplete(self, http_mocker: HttpMocker) -> None: http_mocker.get( _application_fees_request().with_any_query_params().build(), a_response_with_status(400), @@ -248,21 +248,16 @@ def test_given_no_state_when_read_then_use_application_fees_endpoint(self, http_ output = self._read(_config().with_start_date(_A_START_DATE), _NO_STATE) most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_when_read_then_query_events_using_types_and_state_value_plus_1(self, http_mocker: HttpMocker) -> None: start_date = _NOW - timedelta(days=40) state_datetime = _NOW - timedelta(days=5) - cursor_value = int(state_datetime.timestamp()) + 1 + cursor_value = int(state_datetime.timestamp()) http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_record(_an_event().with_cursor(cursor_value).with_field(_DATA_FIELD, _an_application_fee().build())) .build(), @@ -275,18 +270,13 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_and_pagination_when_read_then_return_records(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_pagination() .with_record(_an_event().with_id("last_record_id_from_first_page").with_field(_DATA_FIELD, _an_application_fee().build())) @@ -295,7 +285,7 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc http_mocker.get( _events_request() .with_starting_after("last_record_id_from_first_page") - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_created_gte(state_datetime) .with_created_lte(_NOW) .with_limit(100) .with_types(_EVENT_TYPES) @@ -314,24 +304,19 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc def test_given_state_and_small_slice_range_when_read_then_perform_multiple_queries(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) slice_range = timedelta(days=3) - slice_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + slice_range + slice_datetime = state_datetime + slice_range http_mocker.get( _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(slice_datetime) + .with_created_gte(state_datetime) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .with_types(_EVENT_TYPES) .build(), _events_response().with_record(self._an_application_fee_event()).build(), ) http_mocker.get( - _events_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(self._an_application_fee_event()).with_record(self._an_application_fee_event()).build(), ) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_application_fees_refunds.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_application_fees_refunds.py index 8581688de825a..1772d3528fd38 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_application_fees_refunds.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_application_fees_refunds.py @@ -1,5 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# import json from datetime import datetime, timedelta, timezone @@ -221,17 +222,17 @@ def test_given_slice_range_when_read_then_perform_multiple_requests(self, http_m slice_datetime = start_date + slice_range http_mocker.get( - _application_fees_request().with_created_gte(start_date).with_created_lte(slice_datetime).with_limit(100).build(), + _application_fees_request() + .with_created_gte(start_date) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_limit(100) + .build(), _application_fees_response() .with_record(_an_application_fee().with_field(_REFUNDS_FIELD, _as_dict(_refunds_response().with_record(_a_refund())))) .build(), ) http_mocker.get( - _application_fees_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .build(), + _application_fees_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).build(), _application_fees_response() .with_record(_an_application_fee().with_field(_REFUNDS_FIELD, _as_dict(_refunds_response().with_record(_a_refund())))) .build(), @@ -255,7 +256,11 @@ def test_given_slice_range_and_refunds_pagination_when_read_then_do_not_slice_ch _application_fees_response().build(), ) # catching subsequent slicing request that we don't really care for this test http_mocker.get( - _application_fees_request().with_created_gte(start_date).with_created_lte(slice_datetime).with_limit(100).build(), + _application_fees_request() + .with_created_gte(start_date) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_limit(100) + .build(), _application_fees_response() .with_record( _an_application_fee() @@ -359,7 +364,7 @@ def test_given_no_state_when_read_then_use_application_fees_endpoint(self, http_ most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.state["updated"] == str(cursor_value) @HttpMocker() def test_given_state_when_read_then_query_events_using_types_and_state_value_plus_1(self, http_mocker: HttpMocker) -> None: @@ -368,12 +373,7 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu cursor_value = int(state_datetime.timestamp()) + 1 http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(_an_event().with_cursor(cursor_value).with_field(_DATA_FIELD, _a_refund().build())).build(), ) @@ -384,18 +384,13 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_and_pagination_when_read_then_return_records(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_pagination() .with_record(_an_event().with_id("last_record_id_from_first_page").with_field(_DATA_FIELD, _a_refund().build())) @@ -404,7 +399,7 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc http_mocker.get( _events_request() .with_starting_after("last_record_id_from_first_page") - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_created_gte(state_datetime) .with_created_lte(_NOW) .with_limit(100) .with_types(_EVENT_TYPES) @@ -423,24 +418,19 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc def test_given_state_and_small_slice_range_when_read_then_perform_multiple_queries(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) slice_range = timedelta(days=3) - slice_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + slice_range + slice_datetime = state_datetime + slice_range http_mocker.get( _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(slice_datetime) + .with_created_gte(state_datetime) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .with_types(_EVENT_TYPES) .build(), _events_response().with_record(self._a_refund_event()).build(), ) http_mocker.get( - _events_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(self._a_refund_event()).with_record(self._a_refund_event()).build(), ) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_authorizations.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_authorizations.py index c4a29d2d42d6d..9ec7a0ee69a9e 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_authorizations.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_authorizations.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime, timedelta, timezone from typing import Any, Dict, Optional @@ -161,18 +163,18 @@ def test_given_slice_range_when_read_then_perform_multiple_requests(self, http_m slice_range = timedelta(days=20) slice_datetime = start_date + slice_range - http_mocker.get( - _authorizations_request().with_created_gte(start_date).with_created_lte(slice_datetime).with_limit(100).build(), - _authorizations_response().build(), - ) http_mocker.get( _authorizations_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) + .with_created_gte(start_date) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .build(), _authorizations_response().build(), ) + http_mocker.get( + _authorizations_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).build(), + _authorizations_response().build(), + ) self._read(_config().with_start_date(start_date).with_slice_range_in_days(slice_range.days)) @@ -243,7 +245,7 @@ def test_given_no_state_when_read_then_use_authorizations_endpoint(self, http_mo output = self._read(_config().with_start_date(_A_START_DATE), _NO_STATE) most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_when_read_then_query_events_using_types_and_state_value_plus_1(self, http_mocker: HttpMocker) -> None: @@ -252,12 +254,7 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu cursor_value = int(state_datetime.timestamp()) + 1 http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_record(_an_event().with_cursor(cursor_value).with_field(_DATA_FIELD, _an_authorization().build())) .build(), @@ -270,18 +267,13 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_and_pagination_when_read_then_return_records(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_pagination() .with_record(_an_event().with_id("last_record_id_from_first_page").with_field(_DATA_FIELD, _an_authorization().build())) @@ -290,7 +282,7 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc http_mocker.get( _events_request() .with_starting_after("last_record_id_from_first_page") - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_created_gte(state_datetime) .with_created_lte(_NOW) .with_limit(100) .with_types(_EVENT_TYPES) @@ -309,24 +301,19 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc def test_given_state_and_small_slice_range_when_read_then_perform_multiple_queries(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) slice_range = timedelta(days=3) - slice_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + slice_range + slice_datetime = state_datetime + slice_range http_mocker.get( _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(slice_datetime) + .with_created_gte(state_datetime) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .with_types(_EVENT_TYPES) .build(), _events_response().with_record(self._an_authorization_event()).build(), ) http_mocker.get( - _events_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(self._an_authorization_event()).with_record(self._an_authorization_event()).build(), ) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_bank_accounts.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_bank_accounts.py index 92abc3a33af2b..8bf55eceeaf03 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_bank_accounts.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_bank_accounts.py @@ -1,5 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. - +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# import json from datetime import datetime, timedelta, timezone @@ -158,7 +159,6 @@ def test_given_source_is_not_bank_account_when_read_then_filter_record(self, htt .with_record(_a_customer().with_field(_SOURCES_FIELD, _as_dict(_bank_accounts_response().with_record(_NOT_A_BANK_ACCOUNT)))) .build(), ) - output = self._read(_config().with_start_date(_A_START_DATE)) assert len(output.records) == 0 @@ -242,7 +242,7 @@ def test_given_slice_range_when_read_then_perform_multiple_requests(self, http_m _customers_request() .with_expands(_EXPANDS) .with_created_gte(start_date) - .with_created_lte(slice_datetime) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .build(), _customers_response() @@ -250,12 +250,7 @@ def test_given_slice_range_when_read_then_perform_multiple_requests(self, http_m .build(), ) http_mocker.get( - _customers_request() - .with_expands(_EXPANDS) - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .build(), + _customers_request().with_expands(_EXPANDS).with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).build(), _customers_response() .with_record(_a_customer().with_field(_SOURCES_FIELD, _as_dict(_bank_accounts_response().with_record(_a_bank_account())))) .build(), @@ -282,7 +277,7 @@ def test_given_slice_range_and_bank_accounts_pagination_when_read_then_do_not_sl _customers_request() .with_expands(_EXPANDS) .with_created_gte(start_date) - .with_created_lte(slice_datetime) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .build(), _customers_response() @@ -296,6 +291,7 @@ def test_given_slice_range_and_bank_accounts_pagination_when_read_then_do_not_sl ) .build(), ) + http_mocker.get( # slice range is not applied here _customers_bank_accounts_request("parent_id").with_limit(100).with_starting_after("latest_bank_account_id").build(), @@ -385,7 +381,7 @@ def test_given_no_state_and_successful_sync_when_read_then_set_state_to_now(self most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=int(_NOW.timestamp())) + assert int(most_recent_state.stream_state.state["updated"]) == int(_NOW.timestamp()) @HttpMocker() def test_given_state_when_read_then_query_events_using_types_and_state_value_plus_1(self, http_mocker: HttpMocker) -> None: @@ -394,12 +390,7 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu cursor_value = int(state_datetime.timestamp()) + 1 http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_record(_an_event().with_cursor(cursor_value).with_field(_DATA_FIELD, _a_bank_account().build())) .build(), @@ -412,18 +403,13 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_and_pagination_when_read_then_return_records(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_pagination() .with_record(_an_event().with_id("last_record_id_from_first_page").with_field(_DATA_FIELD, _a_bank_account().build())) @@ -432,7 +418,7 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc http_mocker.get( _events_request() .with_starting_after("last_record_id_from_first_page") - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_created_gte(state_datetime) .with_created_lte(_NOW) .with_limit(100) .with_types(_EVENT_TYPES) @@ -451,24 +437,19 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc def test_given_state_and_small_slice_range_when_read_then_perform_multiple_queries(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) slice_range = timedelta(days=3) - slice_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + slice_range + slice_datetime = state_datetime + slice_range http_mocker.get( _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(slice_datetime) + .with_created_gte(state_datetime) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .with_types(_EVENT_TYPES) .build(), _events_response().with_record(self._a_bank_account_event()).build(), ) http_mocker.get( - _events_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(self._a_bank_account_event()).with_record(self._a_bank_account_event()).build(), ) @@ -509,12 +490,7 @@ def test_given_state_earlier_than_30_days_when_read_then_query_events_using_type def test_given_source_is_not_bank_account_when_read_then_filter_record(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(_an_event().with_field(_DATA_FIELD, _NOT_A_BANK_ACCOUNT.build())).build(), ) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_cards.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_cards.py index d1c037ea9e650..914ab201d87ea 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_cards.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_cards.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime, timedelta, timezone from typing import Any, Dict, Optional @@ -161,18 +163,18 @@ def test_given_slice_range_when_read_then_perform_multiple_requests(self, http_m slice_range = timedelta(days=20) slice_datetime = start_date + slice_range - http_mocker.get( - _cards_request().with_created_gte(start_date).with_created_lte(slice_datetime).with_limit(100).build(), - _cards_response().build(), - ) http_mocker.get( _cards_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) + .with_created_gte(start_date) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .build(), _cards_response().build(), ) + http_mocker.get( + _cards_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).build(), + _cards_response().build(), + ) self._read(_config().with_start_date(start_date).with_slice_range_in_days(slice_range.days)) @@ -187,6 +189,7 @@ def test_given_http_status_400_when_read_then_stream_did_not_run(self, http_mock output = self._read(_config()) assert_stream_did_not_run(output, _STREAM_NAME, "Your account is not set up to use Issuing") + @HttpMocker() @HttpMocker() def test_given_http_status_401_when_read_then_config_error(self, http_mocker: HttpMocker) -> None: http_mocker.get( @@ -243,7 +246,7 @@ def test_given_no_state_when_read_then_use_cards_endpoint(self, http_mocker: Htt output = self._read(_config().with_start_date(_A_START_DATE), _NO_STATE) most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_when_read_then_query_events_using_types_and_state_value_plus_1(self, http_mocker: HttpMocker) -> None: @@ -252,12 +255,7 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu cursor_value = int(state_datetime.timestamp()) + 1 http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(_an_event().with_cursor(cursor_value).with_field(_DATA_FIELD, _a_card().build())).build(), ) @@ -268,18 +266,13 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_and_pagination_when_read_then_return_records(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_pagination() .with_record(_an_event().with_id("last_record_id_from_first_page").with_field(_DATA_FIELD, _a_card().build())) @@ -288,7 +281,7 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc http_mocker.get( _events_request() .with_starting_after("last_record_id_from_first_page") - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_created_gte(state_datetime) .with_created_lte(_NOW) .with_limit(100) .with_types(_EVENT_TYPES) @@ -307,24 +300,19 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc def test_given_state_and_small_slice_range_when_read_then_perform_multiple_queries(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) slice_range = timedelta(days=3) - slice_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + slice_range + slice_datetime = state_datetime + slice_range http_mocker.get( _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(slice_datetime) + .with_created_gte(state_datetime) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .with_types(_EVENT_TYPES) .build(), _events_response().with_record(self._a_card_event()).build(), ) http_mocker.get( - _events_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(self._a_card_event()).with_record(self._a_card_event()).build(), ) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_early_fraud_warnings.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_early_fraud_warnings.py index 7e0c41a080f4c..d74777b472f74 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_early_fraud_warnings.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_early_fraud_warnings.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime, timedelta, timezone from typing import Any, Dict, Optional @@ -207,7 +209,7 @@ def test_given_no_state_when_read_then_use_early_fraud_warnings_endpoint(self, h output = self._read(_config().with_start_date(_A_START_DATE), _NO_STATE) most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_when_read_then_query_events_using_types_and_state_value_plus_1(self, http_mocker: HttpMocker) -> None: @@ -216,12 +218,7 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu cursor_value = int(state_datetime.timestamp()) + 1 http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_record(_an_event().with_cursor(cursor_value).with_field(_DATA_FIELD, _an_early_fraud_warning().build())) .build(), @@ -234,18 +231,13 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_and_pagination_when_read_then_return_records(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_pagination() .with_record(_an_event().with_id("last_record_id_from_first_page").with_field(_DATA_FIELD, _an_early_fraud_warning().build())) @@ -254,7 +246,7 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc http_mocker.get( _events_request() .with_starting_after("last_record_id_from_first_page") - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_created_gte(state_datetime) .with_created_lte(_NOW) .with_limit(100) .with_types(_EVENT_TYPES) @@ -273,24 +265,19 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc def test_given_state_and_small_slice_range_when_read_then_perform_multiple_queries(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) slice_range = timedelta(days=3) - slice_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + slice_range + slice_datetime = state_datetime + slice_range http_mocker.get( _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(slice_datetime) + .with_created_gte(state_datetime) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .with_types(_EVENT_TYPES) .build(), _events_response().with_record(self._an_early_fraud_warning_event()).build(), ) http_mocker.get( - _events_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(self._an_early_fraud_warning_event()).with_record(self._an_early_fraud_warning_event()).build(), ) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_events.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_events.py index 701b149b0bd52..7f46a7c531903 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_events.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_events.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime, timedelta, timezone from typing import Any, Dict, Optional @@ -37,8 +39,6 @@ _CLIENT_SECRET = "client_secret" _NO_STATE = {} _AVOIDING_INCLUSIVE_BOUNDARIES = timedelta(seconds=1) -_SECOND_REQUEST = timedelta(seconds=1) -_THIRD_REQUEST = timedelta(seconds=2) def _a_request() -> StripeRequestBuilder: @@ -120,19 +120,23 @@ def test_given_start_date_before_30_days_stripe_limit_and_slice_range_when_read_ slice_range = timedelta(days=30) slice_datetime = start_date + slice_range http_mocker.get( # this first request has both gte and lte before 30 days even though we know there should not be records returned - _a_request().with_created_gte(start_date).with_created_lte(slice_datetime).with_limit(100).build(), + _a_request() + .with_created_gte(start_date) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_limit(100) + .build(), _a_response().build(), ) http_mocker.get( _a_request() - .with_created_gte(slice_datetime + _SECOND_REQUEST) - .with_created_lte(slice_datetime + slice_range + _SECOND_REQUEST) + .with_created_gte(slice_datetime) + .with_created_lte(slice_datetime + slice_range - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .build(), _a_response().build(), ) http_mocker.get( - _a_request().with_created_gte(slice_datetime + slice_range + _THIRD_REQUEST).with_created_lte(_NOW).with_limit(100).build(), + _a_request().with_created_gte(slice_datetime + slice_range).with_created_lte(_NOW).with_limit(100).build(), _a_response().build(), ) @@ -145,7 +149,7 @@ def test_given_lookback_window_when_read_then_request_before_start_date(self, ht start_date = _NOW - timedelta(days=30) lookback_window = timedelta(days=10) http_mocker.get( - _a_request().with_created_gte(start_date - lookback_window).with_created_lte(_NOW).with_limit(100).build(), + _a_request().with_created_gte(start_date).with_created_lte(_NOW).with_limit(100).build(), _a_response().build(), ) @@ -159,11 +163,15 @@ def test_given_slice_range_when_read_then_perform_multiple_requests(self, http_m slice_range = timedelta(days=20) slice_datetime = start_date + slice_range http_mocker.get( - _a_request().with_created_gte(start_date).with_created_lte(slice_datetime).with_limit(100).build(), + _a_request() + .with_created_gte(start_date) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_limit(100) + .build(), _a_response().build(), ) http_mocker.get( - _a_request().with_created_gte(slice_datetime + _SECOND_REQUEST).with_created_lte(_NOW).with_limit(100).build(), + _a_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).build(), _a_response().build(), ) @@ -244,13 +252,13 @@ def test_given_no_initial_state_when_read_then_return_state_based_on_cursor_fiel output = self._read(_config().with_start_date(_A_START_DATE), _NO_STATE) most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(created=int(cursor_value)) + assert most_recent_state.stream_state.created == str(cursor_value) @HttpMocker() def test_given_state_when_read_then_use_state_for_query_params(self, http_mocker: HttpMocker) -> None: state_value = _A_START_DATE + timedelta(seconds=1) http_mocker.get( - _a_request().with_created_gte(state_value + _AVOIDING_INCLUSIVE_BOUNDARIES).with_created_lte(_NOW).with_limit(100).build(), + _a_request().with_created_gte(state_value).with_created_lte(_NOW).with_limit(100).build(), _a_response().with_record(_a_record()).build(), ) @@ -276,7 +284,7 @@ def test_given_state_more_recent_than_cursor_when_read_then_return_state_based_o most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(created=very_recent_cursor_state) + assert most_recent_state.stream_state.created == str(very_recent_cursor_state) def _read(self, config: ConfigBuilder, state: Optional[Dict[str, Any]], expecting_exception: bool = False) -> EntrypointOutput: return _read(config, SyncMode.incremental, state, expecting_exception) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_external_account_bank_accounts.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_external_account_bank_accounts.py index 95ae64e494a7d..671d6f29e279e 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_external_account_bank_accounts.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_external_account_bank_accounts.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime, timedelta, timezone from typing import Any, Dict, Optional @@ -206,7 +208,7 @@ def test_given_no_state_when_read_then_use_external_accounts_endpoint(self, http output = self._read(_config().with_start_date(_A_START_DATE), _NO_STATE) most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=int(_NOW.timestamp())) + assert int(most_recent_state.stream_state.updated) == int(_NOW.timestamp()) @HttpMocker() def test_given_state_when_read_then_query_events_using_types_and_state_value_plus_1(self, http_mocker: HttpMocker) -> None: @@ -215,12 +217,7 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu cursor_value = int(state_datetime.timestamp()) + 1 http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_record(_an_event().with_cursor(cursor_value).with_field(_DATA_FIELD, _an_external_bank_account().build())) .build(), @@ -233,7 +230,7 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_object_is_not_back_account_when_read_then_filter_out(self, http_mocker: HttpMocker) -> None: @@ -256,12 +253,7 @@ def test_given_object_is_not_back_account_when_read_then_filter_out(self, http_m def test_given_state_and_pagination_when_read_then_return_records(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_pagination() .with_record(_an_event().with_id("last_record_id_from_first_page").with_field(_DATA_FIELD, _an_external_bank_account().build())) @@ -270,7 +262,7 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc http_mocker.get( _events_request() .with_starting_after("last_record_id_from_first_page") - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_created_gte(state_datetime) .with_created_lte(_NOW) .with_limit(100) .with_types(_EVENT_TYPES) @@ -289,24 +281,19 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc def test_given_state_and_small_slice_range_when_read_then_perform_multiple_queries(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) slice_range = timedelta(days=3) - slice_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + slice_range + slice_datetime = state_datetime + slice_range http_mocker.get( _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(slice_datetime) + .with_created_gte(state_datetime) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .with_types(_EVENT_TYPES) .build(), _events_response().with_record(self._an_external_account_event()).build(), ) http_mocker.get( - _events_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(self._an_external_account_event()).with_record(self._an_external_account_event()).build(), ) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_external_account_cards.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_external_account_cards.py index 3e4f6c2adfa7f..9f7da545fadd5 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_external_account_cards.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_external_account_cards.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime, timedelta, timezone from typing import Any, Dict, Optional @@ -144,7 +146,6 @@ def test_when_read_then_add_cursor_field(self, http_mocker: HttpMocker) -> None: ) output = self._read(_config().with_start_date(_A_START_DATE).with_lookback_window_in_days(10)) - assert output.records[0].record.data["updated"] == int(_NOW.timestamp()) @HttpMocker() @@ -211,7 +212,7 @@ def test_given_no_state_when_read_then_use_external_accounts_endpoint(self, http output = self._read(_config().with_start_date(_A_START_DATE), _NO_STATE) most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=int(_NOW.timestamp())) + assert int(most_recent_state.stream_state.updated) == int(_NOW.timestamp()) @HttpMocker() def test_given_state_when_read_then_query_events_using_types_and_state_value_plus_1(self, http_mocker: HttpMocker) -> None: @@ -220,12 +221,7 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu cursor_value = int(state_datetime.timestamp()) + 1 http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_record(_an_event().with_cursor(cursor_value).with_field(_DATA_FIELD, _an_external_account_card().build())) .build(), @@ -238,7 +234,7 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_object_is_not_back_account_when_read_then_filter_out(self, http_mocker: HttpMocker) -> None: @@ -261,12 +257,7 @@ def test_given_object_is_not_back_account_when_read_then_filter_out(self, http_m def test_given_state_and_pagination_when_read_then_return_records(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_pagination() .with_record(_an_event().with_id("last_record_id_from_first_page").with_field(_DATA_FIELD, _an_external_account_card().build())) @@ -275,7 +266,7 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc http_mocker.get( _events_request() .with_starting_after("last_record_id_from_first_page") - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_created_gte(state_datetime) .with_created_lte(_NOW) .with_limit(100) .with_types(_EVENT_TYPES) @@ -294,24 +285,19 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc def test_given_state_and_small_slice_range_when_read_then_perform_multiple_queries(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) slice_range = timedelta(days=3) - slice_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + slice_range + slice_datetime = state_datetime + slice_range http_mocker.get( _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(slice_datetime) + .with_created_gte(state_datetime) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .with_types(_EVENT_TYPES) .build(), _events_response().with_record(self._an_external_account_event()).build(), ) http_mocker.get( - _events_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(self._an_external_account_event()).with_record(self._an_external_account_event()).build(), ) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_payment_methods.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_payment_methods.py index 1c9bb3a5e2af5..79faa05c9408d 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_payment_methods.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_payment_methods.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime, timedelta, timezone from typing import Any, Dict, Optional @@ -244,7 +246,7 @@ def test_given_no_state_when_read_then_use_payment_methods_endpoint(self, http_m output = self._read(_config().with_start_date(_A_START_DATE), _NO_STATE) most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.state["updated"] == cursor_value @HttpMocker() def test_given_state_when_read_then_query_events_using_types_and_state_value_plus_1(self, http_mocker: HttpMocker) -> None: @@ -253,12 +255,7 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu cursor_value = int(state_datetime.timestamp()) + 1 http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_record(_an_event().with_cursor(cursor_value).with_field(_DATA_FIELD, _a_payment_method().build())) .build(), @@ -271,18 +268,13 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_and_pagination_when_read_then_return_records(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_pagination() .with_record(_an_event().with_id("last_record_id_from_first_page").with_field(_DATA_FIELD, _a_payment_method().build())) @@ -291,7 +283,7 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc http_mocker.get( _events_request() .with_starting_after("last_record_id_from_first_page") - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_created_gte(state_datetime) .with_created_lte(_NOW) .with_limit(100) .with_types(_EVENT_TYPES) @@ -310,24 +302,19 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc def test_given_state_and_small_slice_range_when_read_then_perform_multiple_queries(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) slice_range = timedelta(days=3) - slice_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + slice_range + slice_datetime = state_datetime + slice_range http_mocker.get( _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(slice_datetime) + .with_created_gte(state_datetime) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .with_types(_EVENT_TYPES) .build(), _events_response().with_record(self._a_payment_method_event()).build(), ) http_mocker.get( - _events_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(self._a_payment_method_event()).with_record(self._a_payment_method_event()).build(), ) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_payout_balance_transactions.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_payout_balance_transactions.py index 58a3b355ebd61..9ddfc6d2780ce 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_payout_balance_transactions.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_payout_balance_transactions.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime, timedelta, timezone from unittest import TestCase @@ -165,12 +167,7 @@ def test_when_read_then_fetch_from_updated_payouts(self, http_mocker: HttpMocker state = StateBuilder().with_stream_state(_STREAM_NAME, {"updated": int(_STATE_DATE.timestamp())}).build() catalog = _create_catalog(SyncMode.incremental) http_mocker.get( - _events_request() - .with_created_gte(_STATE_DATE + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(_STATE_DATE).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_record(_event_record().with_field(_DATA_FIELD, _create_payout_record().with_id(_A_PAYOUT_ID).build())) .build(), diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_persons.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_persons.py index de4dd3d3126bf..92b5b97780c29 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_persons.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_persons.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime, timedelta, timezone from typing import List @@ -34,10 +36,7 @@ _ACCOUNT_ID = "acct_1G9HZLIEn49ers" _CLIENT_SECRET = "ConfigBuilder default client secret" _NOW = datetime.now(timezone.utc) -_CONFIG = { - "client_secret": _CLIENT_SECRET, - "account_id": _ACCOUNT_ID, -} +_CONFIG = {"client_secret": _CLIENT_SECRET, "account_id": _ACCOUNT_ID} _NO_STATE = StateBuilder().build() _AVOIDING_INCLUSIVE_BOUNDARIES = timedelta(seconds=1) @@ -125,16 +124,21 @@ def test_parent_pagination(self, http_mocker): # First parent stream accounts first page request http_mocker.get( _create_accounts_request().with_limit(100).build(), - _create_response().with_record(record=_create_record("accounts").with_id("last_page_record_id")).with_pagination().build(), + _create_response().with_record(record=_create_record("accounts").with_id("page_record_id")).with_pagination().build(), ) # Second parent stream accounts second page request http_mocker.get( - _create_accounts_request().with_limit(100).with_starting_after("last_page_record_id").build(), + _create_accounts_request().with_limit(100).with_starting_after("page_record_id").build(), _create_response().with_record(record=_create_record("accounts").with_id("last_page_record_id")).build(), ) - # Persons stream first page request + # Persons stream first page request for first parent + http_mocker.get( + _create_persons_request(parent_account_id="page_record_id").with_limit(100).build(), + _create_response().with_record(record=_create_record("persons")).with_record(record=_create_record("persons")).build(), + ) + # Persons stream first page request for second parent http_mocker.get( _create_persons_request(parent_account_id="last_page_record_id").with_limit(100).build(), _create_response().with_record(record=_create_record("persons")).with_record(record=_create_record("persons")).build(), @@ -259,7 +263,7 @@ def test_persons_403_error(self, http_mocker: HttpMocker): @HttpMocker() def test_incremental_with_recent_state(self, http_mocker: HttpMocker): state_datetime = _NOW - timedelta(days=5) - cursor_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + cursor_datetime = state_datetime http_mocker.get( _create_events_request() @@ -283,13 +287,13 @@ def test_incremental_with_recent_state(self, http_mocker: HttpMocker): assert emits_successful_sync_status_messages(actual_messages.get_stream_statuses(_STREAM_NAME)) most_recent_state = actual_messages.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=int(state_datetime.timestamp())) + assert int(most_recent_state.stream_state.updated) == int(state_datetime.timestamp()) assert len(actual_messages.records) == 1 @HttpMocker() def test_incremental_with_deleted_event(self, http_mocker: HttpMocker): state_datetime = _NOW - timedelta(days=5) - cursor_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + cursor_datetime = state_datetime http_mocker.get( _create_events_request() @@ -313,7 +317,7 @@ def test_incremental_with_deleted_event(self, http_mocker: HttpMocker): assert emits_successful_sync_status_messages(actual_messages.get_stream_statuses(_STREAM_NAME)) most_recent_state = actual_messages.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=int(state_datetime.timestamp())) + assert int(most_recent_state.stream_state.updated) == int(state_datetime.timestamp()) assert len(actual_messages.records) == 1 assert actual_messages.records[0].record.data.get("is_deleted") @@ -345,7 +349,7 @@ def test_incremental_with_newer_start_date(self, http_mocker): assert emits_successful_sync_status_messages(actual_messages.get_stream_statuses(_STREAM_NAME)) most_recent_state = actual_messages.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=int(state_datetime.timestamp())) + assert int(most_recent_state.stream_state.updated) == int(start_datetime.timestamp()) assert len(actual_messages.records) == 1 @HttpMocker() @@ -393,7 +397,7 @@ def test_rate_limited_substream_persons(self, http_mocker: HttpMocker) -> None: @HttpMocker() def test_rate_limited_incremental_events(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) - cursor_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + cursor_datetime = state_datetime http_mocker.get( _create_events_request() @@ -420,7 +424,7 @@ def test_rate_limited_incremental_events(self, http_mocker: HttpMocker) -> None: assert emits_successful_sync_status_messages(actual_messages.get_stream_statuses(_STREAM_NAME)) most_recent_state = actual_messages.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name="persons") - assert most_recent_state.stream_state == AirbyteStateBlob(updated=int(state_datetime.timestamp())) + assert int(most_recent_state.stream_state.updated) == int(state_datetime.timestamp()) assert len(actual_messages.records) == 1 @HttpMocker() @@ -444,12 +448,12 @@ def test_rate_limit_max_attempts_exceeded(self, http_mocker: HttpMocker) -> None FailureType.system_error, FailureType.config_error, ] - assert "Request rate limit exceeded" in actual_messages.errors[0].trace.error.internal_message + assert "Too many requests" in actual_messages.errors[0].trace.error.internal_message @HttpMocker() def test_incremental_rate_limit_max_attempts_exceeded(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) - cursor_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + cursor_datetime = state_datetime http_mocker.get( _create_events_request() @@ -472,7 +476,7 @@ def test_incremental_rate_limit_max_attempts_exceeded(self, http_mocker: HttpMoc ) assert len(actual_messages.errors) == 2 - assert "Request rate limit exceeded" in actual_messages.errors[0].trace.error.message + assert "Too many requests" in actual_messages.errors[0].trace.error.internal_message @HttpMocker() def test_server_error_parent_stream_accounts(self, http_mocker: HttpMocker) -> None: diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_reviews.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_reviews.py index 7bc0c7f3d3296..fe31112a272ce 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_reviews.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_reviews.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime, timedelta, timezone from typing import Any, Dict, Optional @@ -161,18 +163,18 @@ def test_given_slice_range_when_read_then_perform_multiple_requests(self, http_m slice_range = timedelta(days=20) slice_datetime = start_date + slice_range - http_mocker.get( - _reviews_request().with_created_gte(start_date).with_created_lte(slice_datetime).with_limit(100).build(), - _reviews_response().build(), - ) http_mocker.get( _reviews_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) + .with_created_gte(start_date) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .build(), _reviews_response().build(), ) + http_mocker.get( + _reviews_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).build(), + _reviews_response().build(), + ) self._read(_config().with_start_date(start_date).with_slice_range_in_days(slice_range.days)) @@ -243,7 +245,7 @@ def test_given_no_state_when_read_then_use_reviews_endpoint(self, http_mocker: H output = self._read(_config().with_start_date(_A_START_DATE), _NO_STATE) most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_when_read_then_query_events_using_types_and_state_value_plus_1(self, http_mocker: HttpMocker) -> None: @@ -252,12 +254,7 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu cursor_value = int(state_datetime.timestamp()) + 1 http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(_an_event().with_cursor(cursor_value).with_field(_DATA_FIELD, _a_review().build())).build(), ) @@ -268,18 +265,13 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_and_pagination_when_read_then_return_records(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_pagination() .with_record(_an_event().with_id("last_record_id_from_first_page").with_field(_DATA_FIELD, _a_review().build())) @@ -288,7 +280,7 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc http_mocker.get( _events_request() .with_starting_after("last_record_id_from_first_page") - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_created_gte(state_datetime) .with_created_lte(_NOW) .with_limit(100) .with_types(_EVENT_TYPES) @@ -307,24 +299,19 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc def test_given_state_and_small_slice_range_when_read_then_perform_multiple_queries(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) slice_range = timedelta(days=3) - slice_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + slice_range + slice_datetime = state_datetime + slice_range http_mocker.get( _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(slice_datetime) + .with_created_gte(state_datetime) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .with_types(_EVENT_TYPES) .build(), _events_response().with_record(self._a_review_event()).build(), ) http_mocker.get( - _events_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(self._a_review_event()).with_record(self._a_review_event()).build(), ) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_setup_attempts.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_setup_attempts.py index 1658ff4c601c1..7edbb591ac27e 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_setup_attempts.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_setup_attempts.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime, timedelta, timezone from typing import Any, Dict, Optional @@ -180,20 +182,11 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu creation_datetime_of_setup_attempt = int(state_datetime.timestamp()) + 5 http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(self._a_setup_intent_event(cursor_value, _SETUP_INTENT_ID_1)).build(), ) http_mocker.get( - _setup_attempts_request(_SETUP_INTENT_ID_1) - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .build(), + _setup_attempts_request(_SETUP_INTENT_ID_1).with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).build(), _setup_attempts_response().with_record(_a_setup_attempt().with_cursor(creation_datetime_of_setup_attempt)).build(), ) @@ -205,7 +198,7 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu assert len(output.records) == 1 most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(created=creation_datetime_of_setup_attempt) + assert int(most_recent_state.stream_state.state["created"]) == int(creation_datetime_of_setup_attempt) def _a_setup_intent_event(self, cursor_value: int, setup_intent_id: str) -> RecordBuilder: return _an_event().with_cursor(cursor_value).with_field(_DATA_FIELD, _a_setup_intent().with_id(setup_intent_id).build()) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_transactions.py b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_transactions.py index 280df52183524..d5ef881d80f6e 100644 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_transactions.py +++ b/airbyte-integrations/connectors/source-stripe/unit_tests/integration/test_transactions.py @@ -1,4 +1,6 @@ -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. +# +# Copyright (c) 2025 Airbyte, Inc., all rights reserved. +# from datetime import datetime, timedelta, timezone from typing import Any, Dict, Optional @@ -161,18 +163,18 @@ def test_given_slice_range_when_read_then_perform_multiple_requests(self, http_m slice_range = timedelta(days=20) slice_datetime = start_date + slice_range - http_mocker.get( - _transactions_request().with_created_gte(start_date).with_created_lte(slice_datetime).with_limit(100).build(), - _transactions_response().build(), - ) http_mocker.get( _transactions_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) + .with_created_gte(start_date) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .build(), _transactions_response().build(), ) + http_mocker.get( + _transactions_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).build(), + _transactions_response().build(), + ) self._read(_config().with_start_date(start_date).with_slice_range_in_days(slice_range.days)) @@ -243,7 +245,7 @@ def test_given_no_state_when_read_then_use_transactions_endpoint(self, http_mock output = self._read(_config().with_start_date(_A_START_DATE), _NO_STATE) most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_when_read_then_query_events_using_types_and_state_value_plus_1(self, http_mocker: HttpMocker) -> None: @@ -252,12 +254,7 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu cursor_value = int(state_datetime.timestamp()) + 1 http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(_an_event().with_cursor(cursor_value).with_field(_DATA_FIELD, _a_transaction().build())).build(), ) @@ -268,18 +265,13 @@ def test_given_state_when_read_then_query_events_using_types_and_state_value_plu most_recent_state = output.most_recent_state assert most_recent_state.stream_descriptor == StreamDescriptor(name=_STREAM_NAME) - assert most_recent_state.stream_state == AirbyteStateBlob(updated=cursor_value) + assert most_recent_state.stream_state.updated == str(cursor_value) @HttpMocker() def test_given_state_and_pagination_when_read_then_return_records(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) http_mocker.get( - _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(state_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response() .with_pagination() .with_record(_an_event().with_id("last_record_id_from_first_page").with_field(_DATA_FIELD, _a_transaction().build())) @@ -288,7 +280,7 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc http_mocker.get( _events_request() .with_starting_after("last_record_id_from_first_page") - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) + .with_created_gte(state_datetime) .with_created_lte(_NOW) .with_limit(100) .with_types(_EVENT_TYPES) @@ -307,24 +299,19 @@ def test_given_state_and_pagination_when_read_then_return_records(self, http_moc def test_given_state_and_small_slice_range_when_read_then_perform_multiple_queries(self, http_mocker: HttpMocker) -> None: state_datetime = _NOW - timedelta(days=5) slice_range = timedelta(days=3) - slice_datetime = state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES + slice_range + slice_datetime = state_datetime + slice_range http_mocker.get( _events_request() - .with_created_gte(state_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(slice_datetime) + .with_created_gte(state_datetime) + .with_created_lte(slice_datetime - _AVOIDING_INCLUSIVE_BOUNDARIES) .with_limit(100) .with_types(_EVENT_TYPES) .build(), _events_response().with_record(self._a_transaction_event()).build(), ) http_mocker.get( - _events_request() - .with_created_gte(slice_datetime + _AVOIDING_INCLUSIVE_BOUNDARIES) - .with_created_lte(_NOW) - .with_limit(100) - .with_types(_EVENT_TYPES) - .build(), + _events_request().with_created_gte(slice_datetime).with_created_lte(_NOW).with_limit(100).with_types(_EVENT_TYPES).build(), _events_response().with_record(self._a_transaction_event()).with_record(self._a_transaction_event()).build(), ) diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/test_source.py b/airbyte-integrations/connectors/source-stripe/unit_tests/test_source.py deleted file mode 100644 index 98128124534e0..0000000000000 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/test_source.py +++ /dev/null @@ -1,136 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# -import datetime -import logging -from contextlib import nullcontext as does_not_raise - -import pytest -from source_stripe import SourceStripe - -from airbyte_cdk.models import ConfiguredAirbyteCatalog, ConfiguredAirbyteCatalogSerializer, SyncMode -from airbyte_cdk.sources.streams.call_rate import CachedLimiterSession, LimiterSession, Rate -from airbyte_cdk.sources.streams.concurrent.adapters import StreamFacade -from airbyte_cdk.test.state_builder import StateBuilder -from airbyte_cdk.utils import AirbyteTracedException - - -logger = logging.getLogger("airbyte") -_ANY_CATALOG = ConfiguredAirbyteCatalogSerializer.load({"streams": []}) -_ANY_CONFIG = {} -_NO_STATE = StateBuilder().build() - - -class CatalogBuilder: - def __init__(self) -> None: - self._streams = [] - - def with_stream(self, name: str, sync_mode: SyncMode) -> "CatalogBuilder": - self._streams.append( - { - "stream": { - "name": name, - "json_schema": {}, - "supported_sync_modes": ["full_refresh", "incremental"], - "source_defined_primary_key": [["id"]], - }, - "primary_key": [["id"]], - "sync_mode": sync_mode.name, - "destination_sync_mode": "overwrite", - } - ) - return self - - def build(self) -> ConfiguredAirbyteCatalog: - return ConfiguredAirbyteCatalogSerializer.load({"streams": self._streams}) - - -def _a_valid_config(): - return {"account_id": 1, "client_secret": "secret"} - - -def test_streams_are_unique(config): - stream_names = [s.name for s in SourceStripe(_ANY_CATALOG, _ANY_CONFIG, _NO_STATE).streams(config=config)] - assert len(stream_names) == len(set(stream_names)) == 47 - - -@pytest.mark.parametrize( - "input_config, expected_error_msg", - ( - ({"lookback_window_days": "month"}, "Invalid lookback window month. Please use only positive integer values or 0."), - ({"start_date": "January First, 2022"}, "Invalid start date January First, 2022. Please use YYYY-MM-DDTHH:MM:SSZ format."), - ({"slice_range": -10}, "Invalid slice range value -10. Please use positive integer values only."), - (_a_valid_config(), None), - ), -) -def test_config_validation(input_config, expected_error_msg): - context = pytest.raises(AirbyteTracedException, match=expected_error_msg) if expected_error_msg else does_not_raise() - with context: - SourceStripe(_ANY_CATALOG, _ANY_CONFIG, _NO_STATE).validate_and_fill_with_defaults(config=input_config) - - -def test_when_streams_return_full_refresh_as_concurrent(): - streams = SourceStripe( - CatalogBuilder().with_stream("bank_accounts", SyncMode.full_refresh).with_stream("customers", SyncMode.incremental).build(), - _a_valid_config(), - _NO_STATE, - ).streams(_a_valid_config()) - - # bank_accounts (as it is defined as full_refresh) - # balance_transactions, events, files, file_links and shipping_rates (as it is always concurrent now) - assert len(list(filter(lambda stream: isinstance(stream, StreamFacade), streams))) == 6 - - -@pytest.mark.parametrize( - "input_config, default_call_limit", - ( - ({"account_id": 1, "client_secret": "secret"}, 100), - ({"account_id": 1, "client_secret": "secret", "call_rate_limit": 10}, 10), - ({"account_id": 1, "client_secret": "secret", "call_rate_limit": 110}, 100), - ({"account_id": 1, "client_secret": "sk_test_some_secret"}, 25), - ({"account_id": 1, "client_secret": "sk_test_some_secret", "call_rate_limit": 10}, 10), - ({"account_id": 1, "client_secret": "sk_test_some_secret", "call_rate_limit": 30}, 25), - ), -) -def test_call_budget_creation(mocker, input_config, default_call_limit): - """Test that call_budget was created with specific config i.e., that first policy has specific matchers.""" - - policy_mock = mocker.patch("source_stripe.source.MovingWindowCallRatePolicy") - matcher_mock = mocker.patch("source_stripe.source.HttpRequestMatcher") - source = SourceStripe(catalog=None, config=input_config, state=_NO_STATE) - - source.get_api_call_budget(input_config) - - policy_mock.assert_has_calls( - calls=[ - mocker.call(matchers=[mocker.ANY, mocker.ANY], rates=[Rate(limit=20, interval=datetime.timedelta(seconds=1))]), - mocker.call(matchers=[], rates=[Rate(limit=default_call_limit, interval=datetime.timedelta(seconds=1))]), - ], - ) - - matcher_mock.assert_has_calls( - calls=[ - mocker.call(url="https://api.stripe.com/v1/files"), - mocker.call(url="https://api.stripe.com/v1/file_links"), - ] - ) - - -def test_call_budget_passed_to_every_stream(mocker): - """Test that each stream has call_budget passed and creates a proper session""" - - prod_config = {"account_id": 1, "client_secret": "secret"} - source = SourceStripe(catalog=None, config=prod_config, state=_NO_STATE) - get_api_call_budget_mock = mocker.patch.object(source, "get_api_call_budget") - - streams = source.streams(prod_config) - - assert streams - get_api_call_budget_mock.assert_called_once() - - for stream in streams: - if isinstance(stream, StreamFacade): - stream = stream._legacy_stream - session = stream._http_client._session - assert isinstance(session, (CachedLimiterSession, LimiterSession)) - assert session._api_budget == get_api_call_budget_mock.return_value diff --git a/airbyte-integrations/connectors/source-stripe/unit_tests/test_streams.py b/airbyte-integrations/connectors/source-stripe/unit_tests/test_streams.py deleted file mode 100644 index 666dcb9e961fd..0000000000000 --- a/airbyte-integrations/connectors/source-stripe/unit_tests/test_streams.py +++ /dev/null @@ -1,1147 +0,0 @@ -# -# Copyright (c) 2023 Airbyte, Inc., all rights reserved. -# - -from urllib.parse import urlencode - -import freezegun -import pendulum -import pytest -from source_stripe.streams import SetupAttempts, StripeStream, UpdatedCursorIncrementalStripeSubStream - - -def read_from_stream(stream, sync_mode, state): - records = [] - for slice_ in stream.stream_slices(sync_mode=sync_mode, stream_state=state): - for record in stream.read_records(sync_mode=sync_mode, stream_slice=slice_, stream_state=state): - records.append(record) - return records - - -def test_request_headers(stream_by_name): - stream = stream_by_name("accounts") - headers = stream.request_headers() - assert headers["Stripe-Version"] == "2022-11-15" - - -bank_accounts_full_refresh_test_case = ( - { - "https://api.stripe.com/v1/customers?expand%5B%5D=data.sources": { - "has_more": False, - "object": "list", - "url": "/v1/customers", - "data": [ - { - "created": 1641038947, - "id": "cus_HezytZRkaQJC8W", - "object": "customer", - "total": 1, - "sources": { - "data": [ - { - "id": "cs_1", - "object": "card", - }, - { - "id": "cs_2", - "object": "bank_account", - }, - ], - "has_more": True, - "object": "list", - "total_count": 4, - "url": "/v1/customers/cus_HezytZRkaQJC8W/sources", - }, - } - ], - }, - "https://api.stripe.com/v1/customers/cus_HezytZRkaQJC8W/bank_accounts?starting_after=cs_2": { - "data": [ - { - "id": "cs_4", - "object": "bank_account", - }, - ], - "has_more": False, - "object": "list", - "url": "/v1/customers/cus_HezytZRkaQJC8W/bank_accounts", - }, - }, - "bank_accounts", - [ - {"id": "cs_2", "object": "bank_account", "updated": 1692802815}, - {"id": "cs_4", "object": "bank_account", "updated": 1692802815}, - ], - "full_refresh", - {}, -) - - -bank_accounts_incremental_test_case = ( - { - "https://api.stripe.com/v1/events?types%5B%5D=customer.source.created&types%5B%5D=customer.source.expiring&types" - "%5B%5D=customer.source.updated&types%5B%5D=customer.source.deleted": { - "data": [ - { - "id": "evt_1NdNFoEcXtiJtvvhBP5mxQmL", - "object": "event", - "api_version": "2020-08-27", - "created": 1692802016, - "data": {"object": {"object": "bank_account", "bank_account": "cs_1K9GK0EcXtiJtvvhSo2LvGqT", "created": 1653341716}}, - "type": "customer.source.created", - }, - { - "id": "evt_1NdNFoEcXtiJtvvhBP5mxQmL", - "object": "event", - "api_version": "2020-08-27", - "created": 1692802017, - "data": {"object": {"object": "card", "card": "cs_1K9GK0EcXtiJtvvhSo2LvGqT", "created": 1653341716}}, - "type": "customer.source.updated", - }, - ], - "has_more": False, - } - }, - "bank_accounts", - [{"object": "bank_account", "bank_account": "cs_1K9GK0EcXtiJtvvhSo2LvGqT", "created": 1653341716, "updated": 1692802016}], - "incremental", - {"updated": 1692802015}, -) - - -@pytest.mark.parametrize( - "requests_mock_map, stream_cls, expected_records, sync_mode, state", - (bank_accounts_incremental_test_case, bank_accounts_full_refresh_test_case), -) -@freezegun.freeze_time("2023-08-23T15:00:15Z") -def test_lazy_substream_data_cursor_value_is_populated( - requests_mock, stream_by_name, config, requests_mock_map, stream_cls, expected_records, sync_mode, state -): - config["start_date"] = str(pendulum.today().subtract(days=3)) - stream = stream_by_name(stream_cls, config) - for url, body in requests_mock_map.items(): - requests_mock.get(url, json=body) - - records = read_from_stream(stream, sync_mode, state) - assert records == expected_records - for record in records: - assert bool(record[stream.cursor_field]) - - -@pytest.mark.parametrize("requests_mock_map, stream_cls, expected_records, sync_mode, state", (bank_accounts_full_refresh_test_case,)) -@freezegun.freeze_time("2023-08-23T15:00:15Z") -def test_lazy_substream_data_is_expanded( - requests_mock, stream_by_name, config, requests_mock_map, stream_cls, expected_records, sync_mode, state -): - config["start_date"] = str(pendulum.today().subtract(days=3)) - stream = stream_by_name("bank_accounts", config) - for url, body in requests_mock_map.items(): - requests_mock.get(url, json=body) - - records = read_from_stream(stream, sync_mode, state) - - assert list(records) == expected_records - assert len(requests_mock.request_history) == 2 - assert urlencode({"expand[]": "data.sources"}) in requests_mock.request_history[0].url - - -@pytest.mark.parametrize( - "requests_mock_map, stream_cls, expected_records, sync_mode, state, expected_object", - ((*bank_accounts_full_refresh_test_case, "bank_account"), (*bank_accounts_incremental_test_case, "bank_account")), -) -@freezegun.freeze_time("2023-08-23T15:00:15Z") -def test_lazy_substream_data_is_filtered( - requests_mock, stream_by_name, config, requests_mock_map, stream_cls, expected_records, sync_mode, state, expected_object -): - config["start_date"] = str(pendulum.today().subtract(days=3)) - stream = stream_by_name(stream_cls, config) - for url, body in requests_mock_map.items(): - requests_mock.get(url, json=body) - - records = read_from_stream(stream, sync_mode, state) - assert records == expected_records - for record in records: - assert record["object"] == expected_object - - -balance_transactions_api_objects = [ - {"id": "txn_1KVQhfEcXtiJtvvhF7ox3YEm", "object": "balance_transaction", "amount": 435, "created": 1653299388, "status": "available"}, - {"id": "txn_tiJtvvhF7ox3YEmKvVQhfEcX", "object": "balance_transaction", "amount": -9164, "created": 1679568588, "status": "available"}, -] - - -refunds_api_objects = [ - { - "id": "re_3NYB8LAHLf1oYfwN3EZRDIfF", - "object": "refund", - "amount": 100, - "charge": "ch_3NYB8LAHLf1oYfwN3P6BxdKj", - "created": 1653299388, - "currency": "usd", - }, - { - "id": "re_Lf1oYfwN3EZRDIfF3NYB8LAH", - "object": "refund", - "amount": 15, - "charge": "ch_YfwN3P6BxdKj3NYB8LAHLf1o", - "created": 1679568588, - "currency": "eur", - }, - # Incremental `Events` endpoint response - { - "id": "evt_3NRL2GEcXtiJtvvh0kjreLyk", - "object": "event", - "api_version": "2020-08-27", - "created": 1666518588, - "data": { - "object": { - "id": "re_3NRL2GEcXtiJtvvh0ahgD9V8", - "object": "refund", - "amount": 15, - "balance_transaction": "txn_3NRL2GEcXtiJtvvh0uhS7L1l", - "charge": "ch_3NRL2GEcXtiJtvvh0XOSc8NL", - "created": 1666518588, - "currency": "usd", - "destination_details": { - "card": { - "reference": "7901352802291512", - "reference_status": "available", - "reference_type": "acquirer_reference_number", - "type": "refund", - }, - "type": "card", - }, - "metadata": {}, - "payment_intent": "pi_3NRL2GEcXtiJtvvh0OiNTz0f", - "reason": None, - "receipt_number": None, - "source_transfer_reversal": None, - "status": "succeeded", - "transfer_reversal": None, - }, - "previous_attributes": {"destination_details": {"card": {"reference": None, "reference_status": "pending"}}}, - }, - "livemode": False, - "pending_webhooks": 0, - "request": {"id": None, "idempotency_key": None}, - "type": "charge.refund.updated", - }, -] - - -@pytest.mark.parametrize( - "requests_mock_map, expected_records, expected_slices, stream_name, sync_mode, state", - ( - ( - { - "/v1/balance_transactions": [ - { - "json": { - "data": [balance_transactions_api_objects[0]], - "has_more": False, - } - }, - { - "json": { - "data": [balance_transactions_api_objects[-1]], - "has_more": False, - } - }, - ], - }, - [ - { - "id": "txn_1KVQhfEcXtiJtvvhF7ox3YEm", - "object": "balance_transaction", - "amount": 435, - "created": 1653299388, - "status": "available", - }, - { - "id": "txn_tiJtvvhF7ox3YEmKvVQhfEcX", - "object": "balance_transaction", - "amount": -9164, - "created": 1679568588, - "status": "available", - }, - ], - [{"created[gte]": 1631199615, "created[lte]": 1662735615}, {"created[gte]": 1662735616, "created[lte]": 1692802815}], - "balance_transactions", - "full_refresh", - {}, - ), - ( - { - "/v1/balance_transactions": [ - { - "json": { - "data": [balance_transactions_api_objects[-1]], - "has_more": False, - } - }, - ], - }, - [ - { - "id": "txn_tiJtvvhF7ox3YEmKvVQhfEcX", - "object": "balance_transaction", - "amount": -9164, - "created": 1679568588, - "status": "available", - }, - ], - [{"created[gte]": 1665308989, "created[lte]": 1692802815}], - "balance_transactions", - "incremental", - {"created": 1666518588}, - ), - ( - { - "/v1/refunds": [ - { - "json": { - "data": [refunds_api_objects[0]], - "has_more": False, - } - }, - { - "json": { - "data": [refunds_api_objects[1]], - "has_more": False, - } - }, - ], - }, - [ - { - "id": "re_3NYB8LAHLf1oYfwN3EZRDIfF", - "object": "refund", - "amount": 100, - "charge": "ch_3NYB8LAHLf1oYfwN3P6BxdKj", - "created": 1653299388, - "currency": "usd", - "updated": 1653299388, - }, - { - "id": "re_Lf1oYfwN3EZRDIfF3NYB8LAH", - "object": "refund", - "amount": 15, - "charge": "ch_YfwN3P6BxdKj3NYB8LAHLf1o", - "created": 1679568588, - "currency": "eur", - "updated": 1679568588, - }, - ], - [{"created[gte]": 1632409215, "created[lte]": 1663945215}, {"created[gte]": 1663945216, "created[lte]": 1692802815}], - "refunds", - "full_refresh", - {}, - ), - ( - { - "/v1/events": [ - { - "json": { - "data": [refunds_api_objects[2]], - "has_more": False, - } - }, - ], - }, - [ - { - "id": "re_3NRL2GEcXtiJtvvh0ahgD9V8", - "object": "refund", - "amount": 15, - "balance_transaction": "txn_3NRL2GEcXtiJtvvh0uhS7L1l", - "charge": "ch_3NRL2GEcXtiJtvvh0XOSc8NL", - "created": 1666518588, - "currency": "usd", - "destination_details": { - "card": { - "reference": "7901352802291512", - "reference_status": "available", - "reference_type": "acquirer_reference_number", - "type": "refund", - }, - "type": "card", - }, - "metadata": {}, - "payment_intent": "pi_3NRL2GEcXtiJtvvh0OiNTz0f", - "reason": None, - "receipt_number": None, - "source_transfer_reversal": None, - "status": "succeeded", - "transfer_reversal": None, - "updated": 1666518588, - } - ], - [{}], - "refunds", - "incremental", - {"created": 1666518588}, - ), - ), -) -@freezegun.freeze_time("2023-08-23T15:00:15Z") -def test_created_cursor_incremental_stream( - requests_mock, requests_mock_map, stream_by_name, expected_records, expected_slices, stream_name, sync_mode, state, config -): - config["start_date"] = str(pendulum.now().subtract(months=23)) - stream = stream_by_name(stream_name, {"lookback_window_days": 14, **config}) - for url, response in requests_mock_map.items(): - requests_mock.get(url, response) - slices = list(stream.stream_slices(sync_mode=sync_mode, stream_state=state)) - assert slices == expected_slices - records = read_from_stream(stream, sync_mode, state) - assert records == expected_records - for record in records: - assert bool(record[stream.cursor_field]) - call_history = iter(requests_mock.request_history) - for slice_ in slices: - call = next(call_history) - assert urlencode(slice_) in call.url - - -@pytest.mark.parametrize( - "start_date, lookback_window, max_days_from_now, stream_state, expected_start_timestamp", - ( - ("2020-01-01T00:00:00Z", 0, 0, {}, "2020-01-01T00:00:00Z"), - ("2020-01-01T00:00:00Z", 14, 0, {}, "2019-12-18T00:00:00Z"), - ("2020-01-01T00:00:00Z", 0, 30, {}, "2023-07-24T15:00:15Z"), - ("2020-01-01T00:00:00Z", 14, 30, {}, "2023-07-24T15:00:15Z"), - ("2020-01-01T00:00:00Z", 0, 0, {"created": pendulum.parse("2022-07-17T00:00:00Z").int_timestamp}, "2022-07-17T00:00:01Z"), - ("2020-01-01T00:00:00Z", 14, 0, {"created": pendulum.parse("2022-07-17T00:00:00Z").int_timestamp}, "2022-07-03T00:00:01Z"), - ("2020-01-01T00:00:00Z", 0, 30, {"created": pendulum.parse("2022-07-17T00:00:00Z").int_timestamp}, "2023-07-24T15:00:15Z"), - ("2020-01-01T00:00:00Z", 14, 30, {"created": pendulum.parse("2022-07-17T00:00:00Z").int_timestamp}, "2023-07-24T15:00:15Z"), - ), -) -@freezegun.freeze_time("2023-08-23T15:00:15Z") -def test_get_start_timestamp( - stream_by_name, config, start_date, lookback_window, max_days_from_now, stream_state, expected_start_timestamp -): - config["start_date"] = start_date - config["lookback_window_days"] = lookback_window - stream = stream_by_name("balance_transactions", config) - stream.start_date_max_days_from_now = max_days_from_now - assert stream.get_start_timestamp(stream_state) == pendulum.parse(expected_start_timestamp).int_timestamp - - -@pytest.mark.parametrize("sync_mode", ("full_refresh", "incremental")) -def test_updated_cursor_incremental_stream_slices(stream_by_name, sync_mode): - stream = stream_by_name("credit_notes") - assert list(stream.stream_slices(sync_mode)) == [{}] - - -@pytest.mark.parametrize( - "last_record, stream_state, expected_state", - (({"updated": 110}, {"updated": 111}, {"updated": 111}), ({"created": 110}, {"updated": 111}, {"updated": 111})), -) -def test_updated_cursor_incremental_stream_get_updated_state(stream_by_name, last_record, stream_state, expected_state): - stream = stream_by_name("credit_notes") - assert stream.get_updated_state(last_record, stream_state) == expected_state - - -@pytest.mark.parametrize("sync_mode", ("full_refresh", "incremental")) -def test_updated_cursor_incremental_stream_read_wo_state(requests_mock, sync_mode, stream_by_name): - requests_mock.get( - "/v1/credit_notes", - [ - { - "json": { - "data": [ - { - "id": "cn_1NGPwmEcXtiJtvvhNXwHpgJF", - "object": "credit_note", - "amount": 8400, - "amount_shipping": 0, - "created": 1686158100, - }, - { - "id": "cn_JtvvhNXwHpgJF1NGPwmEcXti", - "object": "credit_note", - "amount": 350, - "amount_shipping": 150, - "created": 1685861100, - }, - ], - "has_more": False, - } - } - ], - ) - stream = stream_by_name("credit_notes") - records = [record for record in stream.read_records(sync_mode)] - assert records == [ - { - "id": "cn_1NGPwmEcXtiJtvvhNXwHpgJF", - "object": "credit_note", - "amount": 8400, - "amount_shipping": 0, - "updated": 1686158100, - "created": 1686158100, - }, - { - "id": "cn_JtvvhNXwHpgJF1NGPwmEcXti", - "object": "credit_note", - "amount": 350, - "amount_shipping": 150, - "created": 1685861100, - "updated": 1685861100, - }, - ] - - -@freezegun.freeze_time("2023-08-23T00:00:00") -def test_updated_cursor_incremental_stream_read_w_state(requests_mock, stream_by_name): - requests_mock.get( - "/v1/events", - [ - { - "json": { - "data": [ - { - "id": "evt_1NdNFoEcXtiJtvvhBP5mxQmL", - "object": "event", - "api_version": "2020-08-27", - "created": 1691629292, - "data": {"object": {"object": "credit_note", "invoice": "in_1K9GK0EcXtiJtvvhSo2LvGqT", "created": 1653341716}}, - "type": "credit_note.voided", - } - ], - "has_more": False, - } - } - ], - ) - - stream = stream_by_name("credit_notes") - records = [ - record - for record in stream.read_records("incremental", stream_state={"updated": pendulum.parse("2023-01-01T15:00:15Z").int_timestamp}) - ] - assert records == [{"object": "credit_note", "invoice": "in_1K9GK0EcXtiJtvvhSo2LvGqT", "created": 1653341716, "updated": 1691629292}] - - -@freezegun.freeze_time("2023-08-23T15:00:15Z") -def test_setup_attempts(requests_mock, incremental_stream_args): - requests_mock.get( - "/v1/setup_intents", - [ - {"json": {"data": [{"id": 1, "created": 111, "object": "setup_intent"}]}}, - {"json": {"data": [{"id": 2, "created": 222, "object": "setup_intent"}]}}, - ], - ) - requests_mock.get( - "/v1/setup_attempts", - [ - {"json": {"data": [{"id": 1, "created": 112, "object": "setup_attempt"}]}}, - {"json": {"data": [{"id": 2, "created": 230, "object": "setup_attempt"}]}}, - {"json": {"data": [{"id": 3, "created": 345, "object": "setup_attempt"}]}}, - {"json": {"data": [{"id": 4, "created": 450, "object": "setup_attempt"}]}}, - ], - ) - incremental_stream_args["slice_range"] = 1 - incremental_stream_args["lookback_window_days"] = 0 - incremental_stream_args["start_date"] = pendulum.now().subtract(days=2).int_timestamp - stream = SetupAttempts(**incremental_stream_args) - slices = list(stream.stream_slices("full_refresh")) - assert slices == [ - { - "created[gte]": 1692630015, - "created[lte]": 1692716415, - "parent": {"id": 1, "created": 111, "updated": 111, "object": "setup_intent"}, - }, - { - "created[gte]": 1692716416, - "created[lte]": 1692802815, - "parent": {"id": 1, "created": 111, "updated": 111, "object": "setup_intent"}, - }, - { - "created[gte]": 1692630015, - "created[lte]": 1692716415, - "parent": {"id": 2, "created": 222, "updated": 222, "object": "setup_intent"}, - }, - { - "created[gte]": 1692716416, - "created[lte]": 1692802815, - "parent": {"id": 2, "created": 222, "updated": 222, "object": "setup_intent"}, - }, - ] - records = [] - for slice_ in slices: - for record in stream.read_records("full_refresh", stream_slice=slice_): - records.append(record) - assert records == [ - {"id": 1, "created": 112, "object": "setup_attempt"}, - {"id": 2, "created": 230, "object": "setup_attempt"}, - {"id": 3, "created": 345, "object": "setup_attempt"}, - {"id": 4, "created": 450, "object": "setup_attempt"}, - ] - - -def test_persons_wo_state(requests_mock, stream_args): - requests_mock.get("/v1/accounts", json={"data": [{"id": 1, "object": "account", "created": 111}]}) - stream = UpdatedCursorIncrementalStripeSubStream( - name="persons", - path=lambda self, stream_slice, *args, **kwargs: f"accounts/{stream_slice['parent']['id']}/persons", - parent=StripeStream(name="accounts", path="accounts", use_cache=False, **stream_args), - event_types=["person.created", "person.updated", "person.deleted"], - **stream_args, - ) - slices = list(stream.stream_slices("full_refresh")) - assert slices == [{"parent": {"id": 1, "object": "account", "created": 111}}] - requests_mock.get("/v1/accounts/1/persons", json={"data": [{"id": 11, "object": "person", "created": 222}]}) - records = [] - for slice_ in slices: - for record in stream.read_records("full_refresh", stream_slice=slice_): - records.append(record) - assert records == [{"id": 11, "object": "person", "created": 222, "updated": 222}] - - -@freezegun.freeze_time("2023-08-23T15:00:15") -def test_persons_w_state(requests_mock, stream_args): - requests_mock.get( - "/v1/events", - json={ - "data": [ - { - "id": "evt_1NdNFoEcXtiJtvvhBP5mxQmL", - "object": "event", - "api_version": "2020-08-27", - "created": 1691629292, - "data": {"object": {"object": "person", "name": "John", "created": 1653341716}}, - "type": "person.updated", - } - ], - "has_more": False, - }, - ) - stream = UpdatedCursorIncrementalStripeSubStream( - name="persons", - path=lambda self, stream_slice, *args, **kwargs: f"accounts/{stream_slice['parent']['id']}/persons", - parent=StripeStream(name="accounts", path="accounts", use_cache=False, **stream_args), - event_types=["person.created", "person.updated", "person.deleted"], - **stream_args, - ) - slices = list(stream.stream_slices("incremental", stream_state={"updated": pendulum.parse("2023-08-20T00:00:00").int_timestamp})) - assert slices == [{}] - records = [ - record - for record in stream.read_records("incremental", stream_state={"updated": pendulum.parse("2023-08-20T00:00:00").int_timestamp}) - ] - assert records == [{"object": "person", "name": "John", "created": 1653341716, "updated": 1691629292}] - - -@pytest.mark.parametrize("sync_mode, stream_state", (("full_refresh", {}), ("incremental", {}), ("incremental", {"updated": 1693987430}))) -def test_cursorless_incremental_stream(requests_mock, stream_by_name, sync_mode, stream_state): - # Testing streams that *only* have the cursor field value in incremental mode because of API discrepancies, - # e.g. /bank_accounts does not return created/updated date, however /events?type=bank_account.updated returns the update date. - # Key condition here is that the underlying stream has legacy cursor field set to None. - stream = stream_by_name("external_account_bank_accounts") - requests_mock.get( - "/v1/accounts//external_accounts", - json={ - "data": [ - { - "id": "ba_1Nncwa2eZvKYlo2CDILv1Q7N", - "object": "bank_account", - "account": "acct_1032D82eZvKYlo2C", - "bank_name": "STRIPE TEST BANK", - "country": "US", - } - ] - }, - ) - requests_mock.get( - "/v1/events", - json={ - "data": [ - { - "id": "evt_1NdNFoEcXtiJtvvhBP5mxQmL", - "object": "event", - "api_version": "2020-08-27", - "created": 1691629292, - "data": { - "object": { - "id": "ba_1Nncwa2eZvKYlo2CDILv1Q7N", - "object": "bank_account", - "account": "acct_1032D82eZvKYlo2C", - "bank_name": "STRIPE TEST BANK", - "country": "US", - } - }, - "type": "account.external_account.updated", - } - ], - "has_more": False, - }, - ) - for slice_ in stream.stream_slices(sync_mode=sync_mode, stream_state=stream_state): - for record in stream.read_records(sync_mode=sync_mode, stream_state=stream_state, stream_slice=slice_): - stream.get_updated_state(stream_state, record) - # no assertions, this should be just a successful sync - - -@pytest.mark.parametrize("sync_mode, stream_state", (("full_refresh", {}), ("incremental", {}), ("incremental", {"updated": 1693987430}))) -def test_cursorless_incremental_substream(requests_mock, stream_by_name, sync_mode, stream_state): - # same for substreams - stream = stream_by_name("bank_accounts") - requests_mock.get( - "/v1/customers", - json={ - "data": [ - {"id": 1, "created": 1, "object": "customer", "sources": {"data": [{"id": 1, "object": "bank_account"}], "has_more": True}} - ], - "has_more": False, - }, - ) - requests_mock.get("/v1/customers/1/bank_accounts", json={"has_more": False, "data": [{"id": 2, "object": "bank_account"}]}) - requests_mock.get( - "/v1/events", - json={ - "data": [ - { - "id": "evt_1NdNFoEcXtiJtvvhBP5mxQmL", - "object": "event", - "api_version": "2020-08-27", - "created": 1691629292, - "data": { - "object": { - "id": "ba_1Nncwa2eZvKYlo2CDILv1Q7N", - "object": "bank_account", - "account": "acct_1032D82eZvKYlo2C", - "bank_name": "STRIPE TEST BANK", - "country": "US", - } - }, - "type": "account.external_account.updated", - } - ] - }, - ) - for slice_ in stream.stream_slices(sync_mode=sync_mode, stream_state=stream_state): - for record in stream.read_records(sync_mode=sync_mode, stream_state=stream_state, stream_slice=slice_): - stream.get_updated_state(stream_state, record) - - -@pytest.mark.parametrize("stream_name", ("bank_accounts",)) -def test_get_updated_state(stream_name, stream_by_name, requests_mock): - stream = stream_by_name(stream_name) - response = {"data": [{"id": 1, stream.cursor_field: 1695292083}]} - requests_mock.get("/v1/credit_notes", json=response) - requests_mock.get("/v1/balance_transactions", json=response) - requests_mock.get("/v1/invoices", json=response) - requests_mock.get( - "/v1/customers", - json={"data": [{"id": 1, "created": 1695292083, "sources": {"data": [{"id": 1, "object": "bank_account"}], "has_more": False}}]}, - ) - state = {} - for slice_ in stream.stream_slices(sync_mode="incremental", stream_state=state): - for record in stream.read_records(sync_mode="incremental", stream_slice=slice_, stream_state=state): - state = stream.get_updated_state(state, record) - assert state - - -@freezegun.freeze_time("2023-08-23T15:00:15Z") -def test_subscription_items_extra_request_params(requests_mock, stream_by_name, config): - requests_mock.get( - "/v1/subscriptions", - json={ - "object": "list", - "url": "/v1/subscriptions", - "has_more": False, - "data": [ - { - "id": "sub_1OApco2eZvKYlo2CEDCzwLrE", - "object": "subscription", - "created": 1699603174, - "items": { - "object": "list", - "data": [ - { - "id": "si_OynDmET1kQPTbI", - "object": "subscription_item", - "created": 1699603175, - "quantity": 1, - "subscription": "sub_1OApco2eZvKYlo2CEDCzwLrE", - } - ], - "has_more": True, - }, - "latest_invoice": None, - "livemode": False, - } - ], - }, - ) - requests_mock.get( - "/v1/subscription_items?subscription=sub_1OApco2eZvKYlo2CEDCzwLrE", - json={ - "object": "list", - "url": "/v1/subscription_items", - "has_more": False, - "data": [ - { - "id": "si_OynPdzMZykmCWm", - "object": "subscription_item", - "created": 1699603884, - "quantity": 2, - "subscription": "sub_1OApco2eZvKYlo2CEDCzwLrE", - } - ], - }, - ) - config["start_date"] = str(pendulum.now().subtract(days=3)) - stream = stream_by_name("subscription_items", config) - records = read_from_stream(stream, "full_refresh", {}) - assert records == [ - { - "id": "si_OynDmET1kQPTbI", - "object": "subscription_item", - "created": 1699603175, - "quantity": 1, - "subscription": "sub_1OApco2eZvKYlo2CEDCzwLrE", - "subscription_updated": 1699603174, # 1699603175 - }, - { - "id": "si_OynPdzMZykmCWm", - "object": "subscription_item", - "created": 1699603884, - "quantity": 2, - "subscription": "sub_1OApco2eZvKYlo2CEDCzwLrE", - "subscription_updated": 1699603174, - }, - ] - assert len(requests_mock.request_history) == 2 - assert "subscription=sub_1OApco2eZvKYlo2CEDCzwLrE" in requests_mock.request_history[-1].url - - -checkout_session_api_response = { - "/v1/checkout/sessions": { - "object": "list", - "url": "/v1/checkout/sessions", - "has_more": False, - "data": [ - { - "id": "cs_test_a1yxusdFIgDDkWTaKn6JTYniMDBzrmnBiXH8oRSExZt7tcbIzIEoZk1Lre", - "object": "checkout.session", - "created": 1699647441, - "expires_at": 1699647441, - "payment_intent": "pi_1Gt0KQ2eZvKYlo2CeWXUgmhy", - "status": "open", - "line_items": { - "object": "list", - "has_more": False, - "url": "/v1/checkout/sessions", - "data": [ - { - "id": "li_1OB18o2eZvKYlo2CObYam50U", - "object": "item", - "amount_discount": 0, - "amount_subtotal": 0, - "amount_tax": 0, - "amount_total": 0, - "currency": "usd", - } - ], - }, - }, - { - "id": "cs_test_XH8oRSExZt7tcbIzIEoZk1Lrea1yxusdFIgDDkWTaKn6JTYniMDBzrmnBi", - "object": "checkout.session", - "created": 1699744164, - "expires_at": 1699644174, - "payment_intent": "pi_lo2CeWXUgmhy1Gt0KQ2eZvKY", - "status": "open", - "line_items": { - "object": "list", - "has_more": False, - "url": "/v1/checkout/sessions", - "data": [ - { - "id": "li_KYlo2CObYam50U1OB18o2eZv", - "object": "item", - "amount_discount": 0, - "amount_subtotal": 0, - "amount_tax": 0, - "amount_total": 0, - "currency": "usd", - } - ], - }, - }, - ], - } -} - - -checkout_session_line_items_api_response = { - "/v1/checkout/sessions/cs_test_a1yxusdFIgDDkWTaKn6JTYniMDBzrmnBiXH8oRSExZt7tcbIzIEoZk1Lre/line_items": { - "object": "list", - "has_more": False, - "data": [ - { - "id": "li_1OB18o2eZvKYlo2CObYam50U", - "object": "item", - "amount_discount": 0, - "amount_subtotal": 0, - "amount_tax": 0, - "amount_total": 0, - "currency": "usd", - } - ], - "link": "/v1/checkout/sessions/cs_test_a1yxusdFIgDDkWTaKn6JTYniMDBzrmnBiXH8oRSExZt7tcbIzIEoZk1Lre/line_items", - }, - "/v1/checkout/sessions/cs_test_XH8oRSExZt7tcbIzIEoZk1Lrea1yxusdFIgDDkWTaKn6JTYniMDBzrmnBi/line_items": { - "object": "list", - "has_more": False, - "url": "/v1/checkout/sessions/cs_test_XH8oRSExZt7tcbIzIEoZk1Lrea1yxusdFIgDDkWTaKn6JTYniMDBzrmnBi/line_items", - "data": [ - { - "id": "li_KYlo2CObYam50U1OB18o2eZv", - "object": "item", - "amount_discount": 0, - "amount_subtotal": 0, - "amount_tax": 0, - "amount_total": 0, - "currency": "usd", - } - ], - }, -} - - -checkout_session_events_response = { - "/v1/events": { - "data": [ - { - "id": "evt_1NdNFoEcXtiJtvvhBP5mxQmL", - "object": "event", - "api_version": "2020-08-27", - "created": 1699902016, - "data": { - "object": { - "object": "checkout_session", - "checkout_session": "cs_test_a1yxusdFIgDDkWTaKn6JTYniMDBzrmnBiXH8oRSExZt7tcbIzIEoZk1Lre", - "created": 1653341716, - "id": "cs_test_a1yxusdFIgDDkWTaKn6JTYniMDBzrmnBiXH8oRSExZt7tcbIzIEoZk1Lre", - "expires_at": 1692896410, - } - }, - "type": "checkout.session.completed", - }, - { - "id": "evt_XtiJtvvhBP5mxQmL1NdNFoEc", - "object": "event", - "api_version": "2020-08-27", - "created": 1699901630, - "data": { - "object": { - "object": "checkout_session", - "checkout_session": "cs_test_XH8oRSExZt7tcbIzIEoZk1Lrea1yxusdFIgDDkWTaKn6JTYniMDBzrmnBi", - "created": 1653341716, - "id": "cs_test_XH8oRSExZt7tcbIzIEoZk1Lrea1yxusdFIgDDkWTaKn6JTYniMDBzrmnBi", - "expires_at": 1692896410, - } - }, - "type": "checkout.session.completed", - }, - ], - "has_more": False, - }, -} - - -@pytest.mark.parametrize( - "requests_mock_map, stream_name, sync_mode, state, expected_slices", - ( - ( - checkout_session_api_response, - "checkout_sessions_line_items", - "full_refresh", - {}, - [ - { - "parent": { - "id": "cs_test_a1yxusdFIgDDkWTaKn6JTYniMDBzrmnBiXH8oRSExZt7tcbIzIEoZk1Lre", - "object": "checkout.session", - "created": 1699647441, - "updated": 1699647441, - "expires_at": 1699647441, - "payment_intent": "pi_1Gt0KQ2eZvKYlo2CeWXUgmhy", - "status": "open", - "line_items": { - "object": "list", - "has_more": False, - "url": "/v1/checkout/sessions", - "data": [ - { - "id": "li_1OB18o2eZvKYlo2CObYam50U", - "object": "item", - "amount_discount": 0, - "amount_subtotal": 0, - "amount_tax": 0, - "amount_total": 0, - "currency": "usd", - } - ], - }, - } - }, - { - "parent": { - "id": "cs_test_XH8oRSExZt7tcbIzIEoZk1Lrea1yxusdFIgDDkWTaKn6JTYniMDBzrmnBi", - "object": "checkout.session", - "created": 1699744164, - "updated": 1699744164, - "expires_at": 1699644174, - "payment_intent": "pi_lo2CeWXUgmhy1Gt0KQ2eZvKY", - "status": "open", - "line_items": { - "object": "list", - "has_more": False, - "url": "/v1/checkout/sessions", - "data": [ - { - "id": "li_KYlo2CObYam50U1OB18o2eZv", - "object": "item", - "amount_discount": 0, - "amount_subtotal": 0, - "amount_tax": 0, - "amount_total": 0, - "currency": "usd", - } - ], - }, - } - }, - ], - ), - ( - checkout_session_events_response, - "checkout_sessions_line_items", - "incremental", - {"checkout_session_updated": 1685898010}, - [ - { - "parent": { - "object": "checkout_session", - "checkout_session": "cs_test_a1yxusdFIgDDkWTaKn6JTYniMDBzrmnBiXH8oRSExZt7tcbIzIEoZk1Lre", - "created": 1653341716, - "id": "cs_test_a1yxusdFIgDDkWTaKn6JTYniMDBzrmnBiXH8oRSExZt7tcbIzIEoZk1Lre", - "expires_at": 1692896410, - "updated": 1699902016, - } - }, - { - "parent": { - "object": "checkout_session", - "checkout_session": "cs_test_XH8oRSExZt7tcbIzIEoZk1Lrea1yxusdFIgDDkWTaKn6JTYniMDBzrmnBi", - "created": 1653341716, - "updated": 1699901630, - "id": "cs_test_XH8oRSExZt7tcbIzIEoZk1Lrea1yxusdFIgDDkWTaKn6JTYniMDBzrmnBi", - "expires_at": 1692896410, - } - }, - ], - ), - ), -) -@freezegun.freeze_time("2023-08-23T15:00:15") -def test_parent_incremental_substream_stream_slices( - requests_mock, requests_mock_map, stream_by_name, stream_name, sync_mode, state, expected_slices -): - for url, response in requests_mock_map.items(): - requests_mock.get(url, json=response) - - stream = stream_by_name(stream_name) - slices = stream.stream_slices(sync_mode, stream_state=state) - assert list(slices) == expected_slices - - -checkout_session_line_items_slice_to_record_data_map = { - "id": "checkout_session_id", - "expires_at": "checkout_session_expires_at", - "created": "checkout_session_created", - "updated": "checkout_session_updated", -} - - -@pytest.mark.parametrize( - "requests_mock_map, stream_name, sync_mode, state, mapped_fields", - ( - ( - {**checkout_session_api_response, **checkout_session_line_items_api_response}, - "checkout_sessions_line_items", - "full_refresh", - {}, - checkout_session_line_items_slice_to_record_data_map, - ), - ( - {**checkout_session_events_response, **checkout_session_line_items_api_response}, - "checkout_sessions_line_items", - "incremental", - {"checkout_session_updated": 1685898010}, - checkout_session_line_items_slice_to_record_data_map, - ), - ), -) -def test_parent_incremental_substream_records_contain_data_from_slice( - requests_mock, requests_mock_map, stream_by_name, stream_name, sync_mode, state, mapped_fields -): - for url, response in requests_mock_map.items(): - requests_mock.get(url, json=response) - - stream = stream_by_name(stream_name) - for slice_ in stream.stream_slices(sync_mode, stream_state=state): - for record in stream.read_records(sync_mode, stream_slice=slice_, stream_state=state): - for key, value in mapped_fields.items(): - assert slice_["parent"][key] == record[value] - - -@pytest.mark.parametrize( - "requests_mock_map, stream_name, state", - ( - ( - { - "/v1/events": ( - { - "data": [ - { - "id": "evt_1NdNFoEcXtiJtvvhBP5mxQmL", - "object": "event", - "api_version": "2020-08-27", - "created": 1699902016, - "data": { - "object": { - "object": "checkout_session", - "checkout_session": "cs_1K9GK0EcXtiJtvvhSo2LvGqT", - "created": 1653341716, - "id": "cs_1K9GK0EcXtiJtvvhSo2LvGqT", - "expires_at": 1692896410, - } - }, - "type": "checkout.session.completed", - } - ], - "has_more": False, - }, - 200, - ), - "/v1/checkout/sessions/cs_1K9GK0EcXtiJtvvhSo2LvGqT/line_items": ({}, 404), - }, - "checkout_sessions_line_items", - {"checkout_session_updated": 1686934810}, - ), - ), -) -@freezegun.freeze_time("2023-08-23T15:00:15") -def test_parent_incremental_substream_handles_404(requests_mock, requests_mock_map, stream_by_name, stream_name, state, caplog): - for url, (response, status) in requests_mock_map.items(): - requests_mock.get(url, json=response, status_code=status) - - stream = stream_by_name(stream_name) - records = read_from_stream(stream, "incremental", state) - assert records == [] - assert "Data was not found for URL" in caplog.text diff --git a/docs/integrations/sources/stripe.md b/docs/integrations/sources/stripe.md index 96c9329d12d34..e6ead4d2f6dd8 100644 --- a/docs/integrations/sources/stripe.md +++ b/docs/integrations/sources/stripe.md @@ -246,6 +246,7 @@ Each record is marked with `is_deleted` flag when the appropriate event happens | Version | Date | Pull Request | Subject | |:-----------|:-----------|:----------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 5.9.0-rc.1 | 2025-03-18 | [54162](https://github.com/airbytehq/airbyte/pull/54162) | Migrate to low-code | | 5.8.12 | 2025-03-10 | [55682](https://github.com/airbytehq/airbyte/pull/55682) | Promoting release candidate 5.8.10-rc.1 to a main version. | | 5.8.11 | 2025-03-08 | [55598](https://github.com/airbytehq/airbyte/pull/55598) | Update dependencies | | 5.8.10-rc1 | 2025-02-22 | [53670](https://github.com/airbytehq/airbyte/pull/53670) | Update pritbuffer logic |