From 816ff0db1a19b8f2cff23a94ae5d3d453fe9121b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 18:08:53 +0000 Subject: [PATCH 1/7] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 3a2bf15..5b4eee4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 119 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/postgrid/postgrid-f236b45c85d9a03ce8a4aa4c457928e4e3d71a1f73a7dda26ec1a3f90b4881f3.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/postgrid/postgrid-e46d570f006fa7e6aabae02f0b84b040ac7f4d278a6b6fa51d166459de39a547.yml openapi_spec_hash: 3562a11137635f5a513f3c1ae8421fda -config_hash: 4429a41bb9161a59679a1a95b1ec7053 +config_hash: a838529d2fbbafaa1b32ef3126d82881 From 2dae0d01f332ed593a0e256df489a38490e61ac0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 18:22:32 +0000 Subject: [PATCH 2/7] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5b4eee4..468c6e3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 119 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/postgrid/postgrid-e46d570f006fa7e6aabae02f0b84b040ac7f4d278a6b6fa51d166459de39a547.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/postgrid/postgrid-3c7d57bbfb43bd794b71e33005d57e8e05469854cd30340b491df0819d145adc.yml openapi_spec_hash: 3562a11137635f5a513f3c1ae8421fda -config_hash: a838529d2fbbafaa1b32ef3126d82881 +config_hash: c97dc4db121f63642b688d1ec0923a6d From 27918110696bddf2afd84fc854d6a1d7ce139e9a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 14:15:27 +0000 Subject: [PATCH 3/7] feat: Update available premium paper IDs --- .stats.yml | 6 +- src/postgrid/resources/print_mail/letters.py | 304 +++++++++++++- .../resources/print_mail/postcards.py | 384 ++++++++++++++++-- .../resources/print_mail/self_mailers.py | 148 ++++++- src/postgrid/types/print_mail/campaign.py | 30 +- .../print_mail/campaign_create_params.py | 23 +- .../print_mail/campaign_update_params.py | 23 +- src/postgrid/types/print_mail/letter.py | 19 +- .../types/print_mail/letter_create_params.py | 160 ++++++++ src/postgrid/types/print_mail/postcard.py | 30 +- .../print_mail/postcard_create_params.py | 187 ++++++++- .../print_mail/self_mailer_create_params.py | 88 ++++ .../print_mail/test_campaigns.py | 12 +- .../api_resources/print_mail/test_letters.py | 216 ++++++++++ .../print_mail/test_postcards.py | 152 ++++++- .../print_mail/test_self_mailers.py | 168 ++++++++ 16 files changed, 1863 insertions(+), 87 deletions(-) diff --git a/.stats.yml b/.stats.yml index 468c6e3..beca239 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 119 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/postgrid/postgrid-3c7d57bbfb43bd794b71e33005d57e8e05469854cd30340b491df0819d145adc.yml -openapi_spec_hash: 3562a11137635f5a513f3c1ae8421fda -config_hash: c97dc4db121f63642b688d1ec0923a6d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/postgrid/postgrid-d00ba06c82004a1a431d4c1992fc13c65ed4ffc6bb4dcd06f4b1e10037b1cf60.yml +openapi_spec_hash: 45820a4d38f466f15dcbff2d011b098f +config_hash: 4429a41bb9161a59679a1a95b1ec7053 diff --git a/src/postgrid/resources/print_mail/letters.py b/src/postgrid/resources/print_mail/letters.py index 04a3e11..c0dea77 100644 --- a/src/postgrid/resources/print_mail/letters.py +++ b/src/postgrid/resources/print_mail/letters.py @@ -101,6 +101,11 @@ def create( | Omit = omit, merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], + str, + ] + | Omit = omit, perforated_page: Literal[1] | Omit = omit, plastic_card: PlasticCardParam | Omit = omit, return_envelope: str | Omit = omit, @@ -158,6 +163,17 @@ def create( metadata: See the section on Metadata. + paper: Premium paper selection used for this letter. + + Available values include: + + - `standard` + - `premium_paper_letter_standard_white_70lb` + - `premium_paper_letter_standard_white_80lb` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default letter paper is used when configured; otherwise `standard`. + perforated_page: If specified, indicates which letter page is perforated. Currently, only the first page can be perforated. @@ -184,7 +200,56 @@ def create( def create( self, *, + from_: letter_create_params.LetterCreateWithTemplateFrom, template: str, + to: letter_create_params.LetterCreateWithTemplateTo, + address_placement: AddressPlacement | Omit = omit, + attached_pdf: AttachedPdfParam | Omit = omit, + color: bool | Omit = omit, + description: str | Omit = omit, + double_sided: bool | Omit = omit, + envelope: str | Omit = omit, + mailing_class: Literal[ + "first_class", + "standard_class", + "express", + "certified", + "certified_return_receipt", + "registered", + "usps_first_class", + "usps_standard_class", + "usps_eddm", + "usps_express_2_day", + "usps_express_3_day", + "usps_first_class_certified", + "usps_first_class_certified_return_receipt", + "usps_first_class_registered", + "usps_express_3_day_signature_confirmation", + "usps_express_3_day_certified", + "usps_express_3_day_certified_return_receipt", + "ca_post_lettermail", + "ca_post_personalized", + "ca_post_neighbourhood_mail", + "ups_express_overnight", + "ups_express_2_day", + "ups_express_3_day", + "royal_mail_first_class", + "royal_mail_second_class", + "au_post_second_class", + ] + | Omit = omit, + merge_variables: Dict[str, object] | Omit = omit, + metadata: Dict[str, object] | Omit = omit, + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], + str, + ] + | Omit = omit, + perforated_page: Literal[1] | Omit = omit, + plastic_card: PlasticCardParam | Omit = omit, + return_envelope: str | Omit = omit, + send_date: Union[str, datetime] | Omit = omit, + size: LetterSize | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -202,9 +267,64 @@ def create( - Upload the aforementioned PDF file via a multipart form upload request Args: + from_: The contact information of the sender. You can pass contact information inline + here just like you can for the `to`. + template: The template ID for the letter. You can supply _either_ this or `html` but not both. + to: The recipient of this order. You can either supply the contact information + inline here or provide a contact ID. PostGrid will automatically deduplicate + contacts regardless of whether you provide the information inline here or call + the contact creation endpoint. + + address_placement: Enum representing the placement of the address on the letter. + + attached_pdf: Model representing an attached PDF. + + color: Indicates if the letter is in color. + + description: An optional string describing this resource. Will be visible in the API and the + dashboard. + + double_sided: Indicates if the letter is double-sided. + + envelope: The envelope (ID) for the letter. You can either specify a custom envelope ID or + use the default `standard` envelope. + + mailing_class: The mailing class of this order. If not provided, automatically set to + `first_class`. + + merge_variables: These will be merged with the variables in the template or HTML you create this + order with. The keys in this object should match the variable names in the + template _exactly_ as they are case-sensitive. Note that these _do not_ apply to + PDFs uploaded with the order. + + metadata: See the section on Metadata. + + paper: Premium paper selection used for this letter. + + Available values include: + + - `standard` + - `premium_paper_letter_standard_white_70lb` + - `premium_paper_letter_standard_white_80lb` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default letter paper is used when configured; otherwise `standard`. + + perforated_page: If specified, indicates which letter page is perforated. Currently, only the + first page can be perforated. + + plastic_card: Model representing a plastic card. + + return_envelope: The return envelope (ID) sent out with the letter, if any. + + send_date: This order will transition from `ready` to `printing` on the day after this + date. You can use this parameter to schedule orders for a future date. + + size: Enum representing the supported letter sizes. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -259,6 +379,11 @@ def create( | Omit = omit, merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], + str, + ] + | Omit = omit, perforated_page: Literal[1] | Omit = omit, plastic_card: PlasticCardParam | Omit = omit, return_envelope: str | Omit = omit, @@ -315,6 +440,17 @@ def create( metadata: See the section on Metadata. + paper: Premium paper selection used for this letter. + + Available values include: + + - `standard` + - `premium_paper_letter_standard_white_70lb` + - `premium_paper_letter_standard_white_80lb` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default letter paper is used when configured; otherwise `standard`. + perforated_page: If specified, indicates which letter page is perforated. Currently, only the first page can be perforated. @@ -337,15 +473,17 @@ def create( """ ... - @required_args(["from_", "html", "to"], ["template"], ["from_", "pdf", "to"]) + @required_args(["from_", "html", "to"], ["from_", "template", "to"], ["from_", "pdf", "to"]) def create( self, *, from_: letter_create_params.LetterCreateWithHTMLFrom - | letter_create_params.LetterCreateWithPdfFrom - | Omit = omit, + | letter_create_params.LetterCreateWithTemplateFrom + | letter_create_params.LetterCreateWithPdfFrom, html: str | Omit = omit, - to: letter_create_params.LetterCreateWithHTMLTo | letter_create_params.LetterCreateWithPdfTo | Omit = omit, + to: letter_create_params.LetterCreateWithHTMLTo + | letter_create_params.LetterCreateWithTemplateTo + | letter_create_params.LetterCreateWithPdfTo, address_placement: AddressPlacement | Omit = omit, attached_pdf: AttachedPdfParam | Omit = omit, color: bool | Omit = omit, @@ -383,6 +521,11 @@ def create( | Omit = omit, merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], + str, + ] + | Omit = omit, perforated_page: Literal[1] | Omit = omit, plastic_card: PlasticCardParam | Omit = omit, return_envelope: str | Omit = omit, @@ -413,6 +556,7 @@ def create( "mailing_class": mailing_class, "merge_variables": merge_variables, "metadata": metadata, + "paper": paper, "perforated_page": perforated_page, "plastic_card": plastic_card, "return_envelope": return_envelope, @@ -726,6 +870,11 @@ async def create( | Omit = omit, merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], + str, + ] + | Omit = omit, perforated_page: Literal[1] | Omit = omit, plastic_card: PlasticCardParam | Omit = omit, return_envelope: str | Omit = omit, @@ -783,6 +932,17 @@ async def create( metadata: See the section on Metadata. + paper: Premium paper selection used for this letter. + + Available values include: + + - `standard` + - `premium_paper_letter_standard_white_70lb` + - `premium_paper_letter_standard_white_80lb` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default letter paper is used when configured; otherwise `standard`. + perforated_page: If specified, indicates which letter page is perforated. Currently, only the first page can be perforated. @@ -809,7 +969,56 @@ async def create( async def create( self, *, + from_: letter_create_params.LetterCreateWithTemplateFrom, template: str, + to: letter_create_params.LetterCreateWithTemplateTo, + address_placement: AddressPlacement | Omit = omit, + attached_pdf: AttachedPdfParam | Omit = omit, + color: bool | Omit = omit, + description: str | Omit = omit, + double_sided: bool | Omit = omit, + envelope: str | Omit = omit, + mailing_class: Literal[ + "first_class", + "standard_class", + "express", + "certified", + "certified_return_receipt", + "registered", + "usps_first_class", + "usps_standard_class", + "usps_eddm", + "usps_express_2_day", + "usps_express_3_day", + "usps_first_class_certified", + "usps_first_class_certified_return_receipt", + "usps_first_class_registered", + "usps_express_3_day_signature_confirmation", + "usps_express_3_day_certified", + "usps_express_3_day_certified_return_receipt", + "ca_post_lettermail", + "ca_post_personalized", + "ca_post_neighbourhood_mail", + "ups_express_overnight", + "ups_express_2_day", + "ups_express_3_day", + "royal_mail_first_class", + "royal_mail_second_class", + "au_post_second_class", + ] + | Omit = omit, + merge_variables: Dict[str, object] | Omit = omit, + metadata: Dict[str, object] | Omit = omit, + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], + str, + ] + | Omit = omit, + perforated_page: Literal[1] | Omit = omit, + plastic_card: PlasticCardParam | Omit = omit, + return_envelope: str | Omit = omit, + send_date: Union[str, datetime] | Omit = omit, + size: LetterSize | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -827,9 +1036,64 @@ async def create( - Upload the aforementioned PDF file via a multipart form upload request Args: + from_: The contact information of the sender. You can pass contact information inline + here just like you can for the `to`. + template: The template ID for the letter. You can supply _either_ this or `html` but not both. + to: The recipient of this order. You can either supply the contact information + inline here or provide a contact ID. PostGrid will automatically deduplicate + contacts regardless of whether you provide the information inline here or call + the contact creation endpoint. + + address_placement: Enum representing the placement of the address on the letter. + + attached_pdf: Model representing an attached PDF. + + color: Indicates if the letter is in color. + + description: An optional string describing this resource. Will be visible in the API and the + dashboard. + + double_sided: Indicates if the letter is double-sided. + + envelope: The envelope (ID) for the letter. You can either specify a custom envelope ID or + use the default `standard` envelope. + + mailing_class: The mailing class of this order. If not provided, automatically set to + `first_class`. + + merge_variables: These will be merged with the variables in the template or HTML you create this + order with. The keys in this object should match the variable names in the + template _exactly_ as they are case-sensitive. Note that these _do not_ apply to + PDFs uploaded with the order. + + metadata: See the section on Metadata. + + paper: Premium paper selection used for this letter. + + Available values include: + + - `standard` + - `premium_paper_letter_standard_white_70lb` + - `premium_paper_letter_standard_white_80lb` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default letter paper is used when configured; otherwise `standard`. + + perforated_page: If specified, indicates which letter page is perforated. Currently, only the + first page can be perforated. + + plastic_card: Model representing a plastic card. + + return_envelope: The return envelope (ID) sent out with the letter, if any. + + send_date: This order will transition from `ready` to `printing` on the day after this + date. You can use this parameter to schedule orders for a future date. + + size: Enum representing the supported letter sizes. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -884,6 +1148,11 @@ async def create( | Omit = omit, merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], + str, + ] + | Omit = omit, perforated_page: Literal[1] | Omit = omit, plastic_card: PlasticCardParam | Omit = omit, return_envelope: str | Omit = omit, @@ -940,6 +1209,17 @@ async def create( metadata: See the section on Metadata. + paper: Premium paper selection used for this letter. + + Available values include: + + - `standard` + - `premium_paper_letter_standard_white_70lb` + - `premium_paper_letter_standard_white_80lb` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default letter paper is used when configured; otherwise `standard`. + perforated_page: If specified, indicates which letter page is perforated. Currently, only the first page can be perforated. @@ -962,15 +1242,17 @@ async def create( """ ... - @required_args(["from_", "html", "to"], ["template"], ["from_", "pdf", "to"]) + @required_args(["from_", "html", "to"], ["from_", "template", "to"], ["from_", "pdf", "to"]) async def create( self, *, from_: letter_create_params.LetterCreateWithHTMLFrom - | letter_create_params.LetterCreateWithPdfFrom - | Omit = omit, + | letter_create_params.LetterCreateWithTemplateFrom + | letter_create_params.LetterCreateWithPdfFrom, html: str | Omit = omit, - to: letter_create_params.LetterCreateWithHTMLTo | letter_create_params.LetterCreateWithPdfTo | Omit = omit, + to: letter_create_params.LetterCreateWithHTMLTo + | letter_create_params.LetterCreateWithTemplateTo + | letter_create_params.LetterCreateWithPdfTo, address_placement: AddressPlacement | Omit = omit, attached_pdf: AttachedPdfParam | Omit = omit, color: bool | Omit = omit, @@ -1008,6 +1290,11 @@ async def create( | Omit = omit, merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], + str, + ] + | Omit = omit, perforated_page: Literal[1] | Omit = omit, plastic_card: PlasticCardParam | Omit = omit, return_envelope: str | Omit = omit, @@ -1038,6 +1325,7 @@ async def create( "mailing_class": mailing_class, "merge_variables": merge_variables, "metadata": metadata, + "paper": paper, "perforated_page": perforated_page, "plastic_card": plastic_card, "return_envelope": return_envelope, diff --git a/src/postgrid/resources/print_mail/postcards.py b/src/postgrid/resources/print_mail/postcards.py index d7ca458..f95db85 100644 --- a/src/postgrid/resources/print_mail/postcards.py +++ b/src/postgrid/resources/print_mail/postcards.py @@ -88,7 +88,17 @@ def create( | Omit = omit, merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, - paper: str | Omit = omit, + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + | Omit = omit, send_date: Union[str, datetime] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -138,8 +148,19 @@ def create( metadata: See the section on Metadata. - paper: Premium paper identifier. Use "standard" for regular stock or a premium*paper*\\** - ID. + paper: Premium paper selection used for this postcard. + + Available values include: + + - `standard` + - `premium_paper_heavy_1_glossy` + - `premium_paper_postcard_uv_glossy_ss` + - `premium_paper_postcard_uv_glossy_ss_120lb` + - `premium_paper_postcard_satin_ds` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default postcard paper is used when configured; otherwise + `standard`. send_date: This order will transition from `ready` to `printing` on the day after this date. You can use this parameter to schedule orders for a future date. @@ -160,6 +181,53 @@ def create( *, back_template: str, front_template: str, + size: Literal["6x4", "9x6", "11x6"], + to: postcard_create_params.PostcardCreateWithTemplateTo, + description: str | Omit = omit, + from_: postcard_create_params.PostcardCreateWithTemplateFrom | Omit = omit, + mailing_class: Literal[ + "first_class", + "standard_class", + "express", + "certified", + "certified_return_receipt", + "registered", + "usps_first_class", + "usps_standard_class", + "usps_eddm", + "usps_express_2_day", + "usps_express_3_day", + "usps_first_class_certified", + "usps_first_class_certified_return_receipt", + "usps_first_class_registered", + "usps_express_3_day_signature_confirmation", + "usps_express_3_day_certified", + "usps_express_3_day_certified_return_receipt", + "ca_post_lettermail", + "ca_post_personalized", + "ca_post_neighbourhood_mail", + "ups_express_overnight", + "ups_express_2_day", + "ups_express_3_day", + "royal_mail_first_class", + "royal_mail_second_class", + "au_post_second_class", + ] + | Omit = omit, + merge_variables: Dict[str, object] | Omit = omit, + metadata: Dict[str, object] | Omit = omit, + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + | Omit = omit, + send_date: Union[str, datetime] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -184,6 +252,47 @@ def create( front_template: The template ID for the front of the postcard. You can supply _either_ this or `frontHTML` but not both. + size: Enum representing the supported postcard sizes. + + to: The recipient of this order. You can either supply the contact information + inline here or provide a contact ID. PostGrid will automatically deduplicate + contacts regardless of whether you provide the information inline here or call + the contact creation endpoint. + + description: An optional string describing this resource. Will be visible in the API and the + dashboard. + + from_: The contact information of the sender. You can pass contact information inline + here just like you can for the `to`. Unlike other order types, the sender + address is optional for postcards. + + mailing_class: The mailing class of this order. If not provided, automatically set to + `first_class`. + + merge_variables: These will be merged with the variables in the template or HTML you create this + order with. The keys in this object should match the variable names in the + template _exactly_ as they are case-sensitive. Note that these _do not_ apply to + PDFs uploaded with the order. + + metadata: See the section on Metadata. + + paper: Premium paper selection used for this postcard. + + Available values include: + + - `standard` + - `premium_paper_heavy_1_glossy` + - `premium_paper_postcard_uv_glossy_ss` + - `premium_paper_postcard_uv_glossy_ss_120lb` + - `premium_paper_postcard_satin_ds` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default postcard paper is used when configured; otherwise + `standard`. + + send_date: This order will transition from `ready` to `printing` on the day after this + date. You can use this parameter to schedule orders for a future date. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -234,7 +343,17 @@ def create( | Omit = omit, merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, - paper: str | Omit = omit, + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + | Omit = omit, send_date: Union[str, datetime] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -281,8 +400,19 @@ def create( metadata: See the section on Metadata. - paper: Premium paper identifier. Use "standard" for regular stock or a premium*paper*\\** - ID. + paper: Premium paper selection used for this postcard. + + Available values include: + + - `standard` + - `premium_paper_heavy_1_glossy` + - `premium_paper_postcard_uv_glossy_ss` + - `premium_paper_postcard_uv_glossy_ss_120lb` + - `premium_paper_postcard_satin_ds` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default postcard paper is used when configured; otherwise + `standard`. send_date: This order will transition from `ready` to `printing` on the day after this date. You can use this parameter to schedule orders for a future date. @@ -337,7 +467,17 @@ def create( | Omit = omit, merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, - paper: str | Omit = omit, + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + | Omit = omit, send_date: Union[str, datetime] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -384,8 +524,19 @@ def create( metadata: See the section on Metadata. - paper: Premium paper identifier. Use "standard" for regular stock or a premium*paper*\\** - ID. + paper: Premium paper selection used for this postcard. + + Available values include: + + - `standard` + - `premium_paper_heavy_1_glossy` + - `premium_paper_postcard_uv_glossy_ss` + - `premium_paper_postcard_uv_glossy_ss_120lb` + - `premium_paper_postcard_satin_ds` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default postcard paper is used when configured; otherwise + `standard`. send_date: This order will transition from `ready` to `printing` on the day after this date. You can use this parameter to schedule orders for a future date. @@ -401,20 +552,23 @@ def create( ... @required_args( - ["back_html", "front_html", "size", "to"], ["back_template", "front_template"], ["pdf", "size", "to"] + ["back_html", "front_html", "size", "to"], + ["back_template", "front_template", "size", "to"], + ["pdf", "size", "to"], ) def create( self, *, back_html: str | Omit = omit, front_html: str | Omit = omit, - size: Literal["6x4", "9x6", "11x6"] | Omit = omit, + size: Literal["6x4", "9x6", "11x6"], to: postcard_create_params.PostcardCreateWithHTMLTo + | postcard_create_params.PostcardCreateWithTemplateTo | postcard_create_params.PostcardCreateWithPdfurlTo - | postcard_create_params.PostcardCreateWithPdfFileTo - | Omit = omit, + | postcard_create_params.PostcardCreateWithPdfFileTo, description: str | Omit = omit, from_: postcard_create_params.PostcardCreateWithHTMLFrom + | postcard_create_params.PostcardCreateWithTemplateFrom | postcard_create_params.PostcardCreateWithPdfurlFrom | postcard_create_params.PostcardCreateWithPdfFileFrom | Omit = omit, @@ -449,7 +603,17 @@ def create( | Omit = omit, merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, - paper: str | Omit = omit, + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + | Omit = omit, send_date: Union[str, datetime] | Omit = omit, back_template: str | Omit = omit, front_template: str | Omit = omit, @@ -782,7 +946,17 @@ async def create( | Omit = omit, merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, - paper: str | Omit = omit, + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + | Omit = omit, send_date: Union[str, datetime] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -832,8 +1006,19 @@ async def create( metadata: See the section on Metadata. - paper: Premium paper identifier. Use "standard" for regular stock or a premium*paper*\\** - ID. + paper: Premium paper selection used for this postcard. + + Available values include: + + - `standard` + - `premium_paper_heavy_1_glossy` + - `premium_paper_postcard_uv_glossy_ss` + - `premium_paper_postcard_uv_glossy_ss_120lb` + - `premium_paper_postcard_satin_ds` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default postcard paper is used when configured; otherwise + `standard`. send_date: This order will transition from `ready` to `printing` on the day after this date. You can use this parameter to schedule orders for a future date. @@ -854,6 +1039,53 @@ async def create( *, back_template: str, front_template: str, + size: Literal["6x4", "9x6", "11x6"], + to: postcard_create_params.PostcardCreateWithTemplateTo, + description: str | Omit = omit, + from_: postcard_create_params.PostcardCreateWithTemplateFrom | Omit = omit, + mailing_class: Literal[ + "first_class", + "standard_class", + "express", + "certified", + "certified_return_receipt", + "registered", + "usps_first_class", + "usps_standard_class", + "usps_eddm", + "usps_express_2_day", + "usps_express_3_day", + "usps_first_class_certified", + "usps_first_class_certified_return_receipt", + "usps_first_class_registered", + "usps_express_3_day_signature_confirmation", + "usps_express_3_day_certified", + "usps_express_3_day_certified_return_receipt", + "ca_post_lettermail", + "ca_post_personalized", + "ca_post_neighbourhood_mail", + "ups_express_overnight", + "ups_express_2_day", + "ups_express_3_day", + "royal_mail_first_class", + "royal_mail_second_class", + "au_post_second_class", + ] + | Omit = omit, + merge_variables: Dict[str, object] | Omit = omit, + metadata: Dict[str, object] | Omit = omit, + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + | Omit = omit, + send_date: Union[str, datetime] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -878,6 +1110,47 @@ async def create( front_template: The template ID for the front of the postcard. You can supply _either_ this or `frontHTML` but not both. + size: Enum representing the supported postcard sizes. + + to: The recipient of this order. You can either supply the contact information + inline here or provide a contact ID. PostGrid will automatically deduplicate + contacts regardless of whether you provide the information inline here or call + the contact creation endpoint. + + description: An optional string describing this resource. Will be visible in the API and the + dashboard. + + from_: The contact information of the sender. You can pass contact information inline + here just like you can for the `to`. Unlike other order types, the sender + address is optional for postcards. + + mailing_class: The mailing class of this order. If not provided, automatically set to + `first_class`. + + merge_variables: These will be merged with the variables in the template or HTML you create this + order with. The keys in this object should match the variable names in the + template _exactly_ as they are case-sensitive. Note that these _do not_ apply to + PDFs uploaded with the order. + + metadata: See the section on Metadata. + + paper: Premium paper selection used for this postcard. + + Available values include: + + - `standard` + - `premium_paper_heavy_1_glossy` + - `premium_paper_postcard_uv_glossy_ss` + - `premium_paper_postcard_uv_glossy_ss_120lb` + - `premium_paper_postcard_satin_ds` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default postcard paper is used when configured; otherwise + `standard`. + + send_date: This order will transition from `ready` to `printing` on the day after this + date. You can use this parameter to schedule orders for a future date. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -928,7 +1201,17 @@ async def create( | Omit = omit, merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, - paper: str | Omit = omit, + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + | Omit = omit, send_date: Union[str, datetime] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -975,8 +1258,19 @@ async def create( metadata: See the section on Metadata. - paper: Premium paper identifier. Use "standard" for regular stock or a premium*paper*\\** - ID. + paper: Premium paper selection used for this postcard. + + Available values include: + + - `standard` + - `premium_paper_heavy_1_glossy` + - `premium_paper_postcard_uv_glossy_ss` + - `premium_paper_postcard_uv_glossy_ss_120lb` + - `premium_paper_postcard_satin_ds` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default postcard paper is used when configured; otherwise + `standard`. send_date: This order will transition from `ready` to `printing` on the day after this date. You can use this parameter to schedule orders for a future date. @@ -1031,7 +1325,17 @@ async def create( | Omit = omit, merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, - paper: str | Omit = omit, + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + | Omit = omit, send_date: Union[str, datetime] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -1078,8 +1382,19 @@ async def create( metadata: See the section on Metadata. - paper: Premium paper identifier. Use "standard" for regular stock or a premium*paper*\\** - ID. + paper: Premium paper selection used for this postcard. + + Available values include: + + - `standard` + - `premium_paper_heavy_1_glossy` + - `premium_paper_postcard_uv_glossy_ss` + - `premium_paper_postcard_uv_glossy_ss_120lb` + - `premium_paper_postcard_satin_ds` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default postcard paper is used when configured; otherwise + `standard`. send_date: This order will transition from `ready` to `printing` on the day after this date. You can use this parameter to schedule orders for a future date. @@ -1095,20 +1410,23 @@ async def create( ... @required_args( - ["back_html", "front_html", "size", "to"], ["back_template", "front_template"], ["pdf", "size", "to"] + ["back_html", "front_html", "size", "to"], + ["back_template", "front_template", "size", "to"], + ["pdf", "size", "to"], ) async def create( self, *, back_html: str | Omit = omit, front_html: str | Omit = omit, - size: Literal["6x4", "9x6", "11x6"] | Omit = omit, + size: Literal["6x4", "9x6", "11x6"], to: postcard_create_params.PostcardCreateWithHTMLTo + | postcard_create_params.PostcardCreateWithTemplateTo | postcard_create_params.PostcardCreateWithPdfurlTo - | postcard_create_params.PostcardCreateWithPdfFileTo - | Omit = omit, + | postcard_create_params.PostcardCreateWithPdfFileTo, description: str | Omit = omit, from_: postcard_create_params.PostcardCreateWithHTMLFrom + | postcard_create_params.PostcardCreateWithTemplateFrom | postcard_create_params.PostcardCreateWithPdfurlFrom | postcard_create_params.PostcardCreateWithPdfFileFrom | Omit = omit, @@ -1143,7 +1461,17 @@ async def create( | Omit = omit, merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, - paper: str | Omit = omit, + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + | Omit = omit, send_date: Union[str, datetime] | Omit = omit, back_template: str | Omit = omit, front_template: str | Omit = omit, diff --git a/src/postgrid/resources/print_mail/self_mailers.py b/src/postgrid/resources/print_mail/self_mailers.py index 4ad5f4b..8a6f771 100644 --- a/src/postgrid/resources/print_mail/self_mailers.py +++ b/src/postgrid/resources/print_mail/self_mailers.py @@ -153,8 +153,44 @@ def create( def create( self, *, + from_: self_mailer_create_params.SelfMailerCreateWithTemplateFrom, inside_template: str, outside_template: str, + size: Literal["8.5x11_bifold", "8.5x11_trifold", "9.5x16_trifold"], + to: self_mailer_create_params.SelfMailerCreateWithTemplateTo, + description: str | Omit = omit, + mailing_class: Literal[ + "first_class", + "standard_class", + "express", + "certified", + "certified_return_receipt", + "registered", + "usps_first_class", + "usps_standard_class", + "usps_eddm", + "usps_express_2_day", + "usps_express_3_day", + "usps_first_class_certified", + "usps_first_class_certified_return_receipt", + "usps_first_class_registered", + "usps_express_3_day_signature_confirmation", + "usps_express_3_day_certified", + "usps_express_3_day_certified_return_receipt", + "ca_post_lettermail", + "ca_post_personalized", + "ca_post_neighbourhood_mail", + "ups_express_overnight", + "ups_express_2_day", + "ups_express_3_day", + "royal_mail_first_class", + "royal_mail_second_class", + "au_post_second_class", + ] + | Omit = omit, + merge_variables: Dict[str, object] | Omit = omit, + metadata: Dict[str, object] | Omit = omit, + send_date: Union[str, datetime] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -173,12 +209,38 @@ def create( - Upload the aforementioned PDF file via a multipart form upload request Args: + from_: The contact information of the sender. You can pass contact information inline + here just like you can for the `to`. + inside_template: The template ID for the inside of the self-mailer. You can supply _either_ this or `insideHTML` but not both. outside_template: The template ID for the outside of the self-mailer. You can supply _either_ this or `outsideHTML` but not both. + size: Enum representing the supported self-mailer sizes. + + to: The recipient of this order. You can either supply the contact information + inline here or provide a contact ID. PostGrid will automatically deduplicate + contacts regardless of whether you provide the information inline here or call + the contact creation endpoint. + + description: An optional string describing this resource. Will be visible in the API and the + dashboard. + + mailing_class: The mailing class of this order. If not provided, automatically set to + `first_class`. + + merge_variables: These will be merged with the variables in the template or HTML you create this + order with. The keys in this object should match the variable names in the + template _exactly_ as they are case-sensitive. Note that these _do not_ apply to + PDFs uploaded with the order. + + metadata: See the section on Metadata. + + send_date: This order will transition from `ready` to `printing` on the day after this + date. You can use this parameter to schedule orders for a future date. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -388,23 +450,23 @@ def create( @required_args( ["from_", "inside_html", "outside_html", "size", "to"], - ["inside_template", "outside_template"], + ["from_", "inside_template", "outside_template", "size", "to"], ["from_", "pdf", "size", "to"], ) def create( self, *, from_: self_mailer_create_params.SelfMailerCreateWithHTMLFrom + | self_mailer_create_params.SelfMailerCreateWithTemplateFrom | self_mailer_create_params.SelfMailerCreateWithPdfurlFrom - | self_mailer_create_params.SelfMailerCreateWithPdfFileFrom - | Omit = omit, + | self_mailer_create_params.SelfMailerCreateWithPdfFileFrom, inside_html: str | Omit = omit, outside_html: str | Omit = omit, - size: Literal["8.5x11_bifold", "8.5x11_trifold", "9.5x16_trifold"] | Omit = omit, + size: Literal["8.5x11_bifold", "8.5x11_trifold", "9.5x16_trifold"], to: self_mailer_create_params.SelfMailerCreateWithHTMLTo + | self_mailer_create_params.SelfMailerCreateWithTemplateTo | self_mailer_create_params.SelfMailerCreateWithPdfurlTo - | self_mailer_create_params.SelfMailerCreateWithPdfFileTo - | Omit = omit, + | self_mailer_create_params.SelfMailerCreateWithPdfFileTo, description: str | Omit = omit, mailing_class: Literal[ "first_class", @@ -796,8 +858,44 @@ async def create( async def create( self, *, + from_: self_mailer_create_params.SelfMailerCreateWithTemplateFrom, inside_template: str, outside_template: str, + size: Literal["8.5x11_bifold", "8.5x11_trifold", "9.5x16_trifold"], + to: self_mailer_create_params.SelfMailerCreateWithTemplateTo, + description: str | Omit = omit, + mailing_class: Literal[ + "first_class", + "standard_class", + "express", + "certified", + "certified_return_receipt", + "registered", + "usps_first_class", + "usps_standard_class", + "usps_eddm", + "usps_express_2_day", + "usps_express_3_day", + "usps_first_class_certified", + "usps_first_class_certified_return_receipt", + "usps_first_class_registered", + "usps_express_3_day_signature_confirmation", + "usps_express_3_day_certified", + "usps_express_3_day_certified_return_receipt", + "ca_post_lettermail", + "ca_post_personalized", + "ca_post_neighbourhood_mail", + "ups_express_overnight", + "ups_express_2_day", + "ups_express_3_day", + "royal_mail_first_class", + "royal_mail_second_class", + "au_post_second_class", + ] + | Omit = omit, + merge_variables: Dict[str, object] | Omit = omit, + metadata: Dict[str, object] | Omit = omit, + send_date: Union[str, datetime] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -816,12 +914,38 @@ async def create( - Upload the aforementioned PDF file via a multipart form upload request Args: + from_: The contact information of the sender. You can pass contact information inline + here just like you can for the `to`. + inside_template: The template ID for the inside of the self-mailer. You can supply _either_ this or `insideHTML` but not both. outside_template: The template ID for the outside of the self-mailer. You can supply _either_ this or `outsideHTML` but not both. + size: Enum representing the supported self-mailer sizes. + + to: The recipient of this order. You can either supply the contact information + inline here or provide a contact ID. PostGrid will automatically deduplicate + contacts regardless of whether you provide the information inline here or call + the contact creation endpoint. + + description: An optional string describing this resource. Will be visible in the API and the + dashboard. + + mailing_class: The mailing class of this order. If not provided, automatically set to + `first_class`. + + merge_variables: These will be merged with the variables in the template or HTML you create this + order with. The keys in this object should match the variable names in the + template _exactly_ as they are case-sensitive. Note that these _do not_ apply to + PDFs uploaded with the order. + + metadata: See the section on Metadata. + + send_date: This order will transition from `ready` to `printing` on the day after this + date. You can use this parameter to schedule orders for a future date. + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -1031,23 +1155,23 @@ async def create( @required_args( ["from_", "inside_html", "outside_html", "size", "to"], - ["inside_template", "outside_template"], + ["from_", "inside_template", "outside_template", "size", "to"], ["from_", "pdf", "size", "to"], ) async def create( self, *, from_: self_mailer_create_params.SelfMailerCreateWithHTMLFrom + | self_mailer_create_params.SelfMailerCreateWithTemplateFrom | self_mailer_create_params.SelfMailerCreateWithPdfurlFrom - | self_mailer_create_params.SelfMailerCreateWithPdfFileFrom - | Omit = omit, + | self_mailer_create_params.SelfMailerCreateWithPdfFileFrom, inside_html: str | Omit = omit, outside_html: str | Omit = omit, - size: Literal["8.5x11_bifold", "8.5x11_trifold", "9.5x16_trifold"] | Omit = omit, + size: Literal["8.5x11_bifold", "8.5x11_trifold", "9.5x16_trifold"], to: self_mailer_create_params.SelfMailerCreateWithHTMLTo + | self_mailer_create_params.SelfMailerCreateWithTemplateTo | self_mailer_create_params.SelfMailerCreateWithPdfurlTo - | self_mailer_create_params.SelfMailerCreateWithPdfFileTo - | Omit = omit, + | self_mailer_create_params.SelfMailerCreateWithPdfFileTo, description: str | Omit = omit, mailing_class: Literal[ "first_class", diff --git a/src/postgrid/types/print_mail/campaign.py b/src/postgrid/types/print_mail/campaign.py index aa84dd2..b6ae315 100644 --- a/src/postgrid/types/print_mail/campaign.py +++ b/src/postgrid/types/print_mail/campaign.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Dict, List, Optional +from typing import Dict, List, Union, Optional from datetime import datetime from typing_extensions import Literal @@ -181,6 +181,16 @@ class Letter(BaseModel): metadata: Optional[Dict[str, str]] = None """Optional key-value metadata.""" + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], + str, + None, + ] = None + """Premium paper selection ("standard" or a premium paper ID). + + If omitted, org default is used when configured; otherwise "standard". + """ + perforated_page: Optional[Literal[1]] = FieldInfo(alias="perforatedPage", default=None) """Which page number should be perforated (if any).""" @@ -250,10 +260,20 @@ class Postcard(BaseModel): metadata: Optional[Dict[str, str]] = None """Optional key-value metadata.""" - paper: Optional[str] = None - """Premium paper identifier. - - Use "standard" for regular stock or a premium*paper*\\** ID. + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + None, + ] = None + """Premium paper selection ("standard" or a premium paper ID). + + If omitted, org default is used when configured; otherwise "standard". """ size: Optional[Literal["6x4", "9x6", "11x6"]] = None diff --git a/src/postgrid/types/print_mail/campaign_create_params.py b/src/postgrid/types/print_mail/campaign_create_params.py index 50de448..d711cad 100644 --- a/src/postgrid/types/print_mail/campaign_create_params.py +++ b/src/postgrid/types/print_mail/campaign_create_params.py @@ -238,6 +238,14 @@ class Letter(TypedDict, total=False): metadata: Dict[str, str] """Optional key-value metadata.""" + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], str + ] + """Premium paper selection ("standard" or a premium paper ID). + + If omitted, org default is used when configured; otherwise "standard". + """ + pdf: str """A PDF file or URL for the letter content. Cannot be used with `template`.""" @@ -308,10 +316,19 @@ class Postcard(TypedDict, total=False): metadata: Dict[str, str] """Optional key-value metadata.""" - paper: str - """Premium paper identifier. + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + """Premium paper selection ("standard" or a premium paper ID). - Use "standard" for regular stock or a premium*paper*\\** ID. + If omitted, org default is used when configured; otherwise "standard". """ pdf: str diff --git a/src/postgrid/types/print_mail/campaign_update_params.py b/src/postgrid/types/print_mail/campaign_update_params.py index 406779c..25af9a0 100644 --- a/src/postgrid/types/print_mail/campaign_update_params.py +++ b/src/postgrid/types/print_mail/campaign_update_params.py @@ -232,6 +232,14 @@ class Letter(TypedDict, total=False): metadata: Dict[str, str] """Optional key-value metadata.""" + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], str + ] + """Premium paper selection ("standard" or a premium paper ID). + + If omitted, org default is used when configured; otherwise "standard". + """ + pdf: str """A PDF file or URL for the letter content. Cannot be used with `template`.""" @@ -302,10 +310,19 @@ class Postcard(TypedDict, total=False): metadata: Dict[str, str] """Optional key-value metadata.""" - paper: str - """Premium paper identifier. + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + """Premium paper selection ("standard" or a premium paper ID). - Use "standard" for regular stock or a premium*paper*\\** ID. + If omitted, org default is used when configured; otherwise "standard". """ pdf: str diff --git a/src/postgrid/types/print_mail/letter.py b/src/postgrid/types/print_mail/letter.py index bf432f6..a8a7394 100644 --- a/src/postgrid/types/print_mail/letter.py +++ b/src/postgrid/types/print_mail/letter.py @@ -1,7 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import builtins -from typing import Dict, Optional +from typing import Dict, Union, Optional from datetime import datetime from typing_extensions import Literal @@ -171,6 +171,23 @@ class Letter(BaseModel): metadata: Optional[Dict[str, builtins.object]] = None """See the section on Metadata.""" + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], + str, + None, + ] = None + """Premium paper selection used for this letter. + + Available values include: + + - `standard` + - `premium_paper_letter_standard_white_70lb` + - `premium_paper_letter_standard_white_80lb` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default letter paper is used when configured; otherwise `standard`. + """ + pdf_workflow_run: Optional[str] = FieldInfo(alias="pdfWorkflowRun", default=None) """The ID of the PDF workflow run that created the letter, if any.""" diff --git a/src/postgrid/types/print_mail/letter_create_params.py b/src/postgrid/types/print_mail/letter_create_params.py index 6fc7c27..53b146f 100644 --- a/src/postgrid/types/print_mail/letter_create_params.py +++ b/src/postgrid/types/print_mail/letter_create_params.py @@ -20,6 +20,8 @@ "LetterCreateWithHTMLFrom", "LetterCreateWithHTMLTo", "LetterCreateWithTemplate", + "LetterCreateWithTemplateFrom", + "LetterCreateWithTemplateTo", "LetterCreateWithPdf", "LetterCreateWithPdfFrom", "LetterCreateWithPdfTo", @@ -119,6 +121,21 @@ class LetterCreateWithHTML(TypedDict, total=False): metadata: Dict[str, object] """See the section on Metadata.""" + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], str + ] + """Premium paper selection used for this letter. + + Available values include: + + - `standard` + - `premium_paper_letter_standard_white_70lb` + - `premium_paper_letter_standard_white_80lb` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default letter paper is used when configured; otherwise `standard`. + """ + perforated_page: Annotated[Literal[1], PropertyInfo(alias="perforatedPage")] """If specified, indicates which letter page is perforated. @@ -148,12 +165,140 @@ class LetterCreateWithHTML(TypedDict, total=False): class LetterCreateWithTemplate(TypedDict, total=False): + from_: Required[Annotated[LetterCreateWithTemplateFrom, PropertyInfo(alias="from")]] + """The contact information of the sender. + + You can pass contact information inline here just like you can for the `to`. + """ + template: Required[str] """The template ID for the letter. You can supply _either_ this or `html` but not both. """ + to: Required[LetterCreateWithTemplateTo] + """The recipient of this order. + + You can either supply the contact information inline here or provide a contact + ID. PostGrid will automatically deduplicate contacts regardless of whether you + provide the information inline here or call the contact creation endpoint. + """ + + address_placement: Annotated[AddressPlacement, PropertyInfo(alias="addressPlacement")] + """Enum representing the placement of the address on the letter.""" + + attached_pdf: Annotated[AttachedPdfParam, PropertyInfo(alias="attachedPDF")] + """Model representing an attached PDF.""" + + color: bool + """Indicates if the letter is in color.""" + + description: str + """An optional string describing this resource. + + Will be visible in the API and the dashboard. + """ + + double_sided: Annotated[bool, PropertyInfo(alias="doubleSided")] + """Indicates if the letter is double-sided.""" + + envelope: str + """The envelope (ID) for the letter. + + You can either specify a custom envelope ID or use the default `standard` + envelope. + """ + + mailing_class: Annotated[ + Literal[ + "first_class", + "standard_class", + "express", + "certified", + "certified_return_receipt", + "registered", + "usps_first_class", + "usps_standard_class", + "usps_eddm", + "usps_express_2_day", + "usps_express_3_day", + "usps_first_class_certified", + "usps_first_class_certified_return_receipt", + "usps_first_class_registered", + "usps_express_3_day_signature_confirmation", + "usps_express_3_day_certified", + "usps_express_3_day_certified_return_receipt", + "ca_post_lettermail", + "ca_post_personalized", + "ca_post_neighbourhood_mail", + "ups_express_overnight", + "ups_express_2_day", + "ups_express_3_day", + "royal_mail_first_class", + "royal_mail_second_class", + "au_post_second_class", + ], + PropertyInfo(alias="mailingClass"), + ] + """The mailing class of this order. + + If not provided, automatically set to `first_class`. + """ + + merge_variables: Annotated[Dict[str, object], PropertyInfo(alias="mergeVariables")] + """ + These will be merged with the variables in the template or HTML you create this + order with. The keys in this object should match the variable names in the + template _exactly_ as they are case-sensitive. Note that these _do not_ apply to + PDFs uploaded with the order. + """ + + metadata: Dict[str, object] + """See the section on Metadata.""" + + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], str + ] + """Premium paper selection used for this letter. + + Available values include: + + - `standard` + - `premium_paper_letter_standard_white_70lb` + - `premium_paper_letter_standard_white_80lb` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default letter paper is used when configured; otherwise `standard`. + """ + + perforated_page: Annotated[Literal[1], PropertyInfo(alias="perforatedPage")] + """If specified, indicates which letter page is perforated. + + Currently, only the first page can be perforated. + """ + + plastic_card: Annotated[PlasticCardParam, PropertyInfo(alias="plasticCard")] + """Model representing a plastic card.""" + + return_envelope: Annotated[str, PropertyInfo(alias="returnEnvelope")] + """The return envelope (ID) sent out with the letter, if any.""" + + send_date: Annotated[Union[str, datetime], PropertyInfo(alias="sendDate", format="iso8601")] + """This order will transition from `ready` to `printing` on the day after this + date. + + You can use this parameter to schedule orders for a future date. + """ + + size: LetterSize + """Enum representing the supported letter sizes.""" + + +LetterCreateWithTemplateFrom: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] + +LetterCreateWithTemplateTo: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] + class LetterCreateWithPdf(TypedDict, total=False): from_: Required[Annotated[LetterCreateWithPdfFrom, PropertyInfo(alias="from")]] @@ -245,6 +390,21 @@ class LetterCreateWithPdf(TypedDict, total=False): metadata: Dict[str, object] """See the section on Metadata.""" + paper: Union[ + Literal["standard", "premium_paper_letter_standard_white_70lb", "premium_paper_letter_standard_white_80lb"], str + ] + """Premium paper selection used for this letter. + + Available values include: + + - `standard` + - `premium_paper_letter_standard_white_70lb` + - `premium_paper_letter_standard_white_80lb` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default letter paper is used when configured; otherwise `standard`. + """ + perforated_page: Annotated[Literal[1], PropertyInfo(alias="perforatedPage")] """If specified, indicates which letter page is perforated. diff --git a/src/postgrid/types/print_mail/postcard.py b/src/postgrid/types/print_mail/postcard.py index e692605..32777b1 100644 --- a/src/postgrid/types/print_mail/postcard.py +++ b/src/postgrid/types/print_mail/postcard.py @@ -1,7 +1,7 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import builtins -from typing import Dict, Optional +from typing import Dict, Union, Optional from datetime import datetime from typing_extensions import Literal @@ -146,10 +146,30 @@ class Postcard(BaseModel): metadata: Optional[Dict[str, builtins.object]] = None """See the section on Metadata.""" - paper: Optional[str] = None - """Premium paper identifier. - - Use "standard" for regular stock or a premium*paper*\\** ID. + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + None, + ] = None + """Premium paper selection used for this postcard. + + Available values include: + + - `standard` + - `premium_paper_heavy_1_glossy` + - `premium_paper_postcard_uv_glossy_ss` + - `premium_paper_postcard_uv_glossy_ss_120lb` + - `premium_paper_postcard_satin_ds` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default postcard paper is used when configured; otherwise + `standard`. """ tracking_number: Optional[str] = FieldInfo(alias="trackingNumber", default=None) diff --git a/src/postgrid/types/print_mail/postcard_create_params.py b/src/postgrid/types/print_mail/postcard_create_params.py index 473f147..247697b 100644 --- a/src/postgrid/types/print_mail/postcard_create_params.py +++ b/src/postgrid/types/print_mail/postcard_create_params.py @@ -17,6 +17,8 @@ "PostcardCreateWithHTMLTo", "PostcardCreateWithHTMLFrom", "PostcardCreateWithTemplate", + "PostcardCreateWithTemplateTo", + "PostcardCreateWithTemplateFrom", "PostcardCreateWithPdfurl", "PostcardCreateWithPdfurlTo", "PostcardCreateWithPdfurlFrom", @@ -110,10 +112,29 @@ class PostcardCreateWithHTML(TypedDict, total=False): metadata: Dict[str, object] """See the section on Metadata.""" - paper: str - """Premium paper identifier. + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + """Premium paper selection used for this postcard. + + Available values include: - Use "standard" for regular stock or a premium*paper*\\** ID. + - `standard` + - `premium_paper_heavy_1_glossy` + - `premium_paper_postcard_uv_glossy_ss` + - `premium_paper_postcard_uv_glossy_ss_120lb` + - `premium_paper_postcard_satin_ds` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default postcard paper is used when configured; otherwise + `standard`. """ send_date: Annotated[Union[str, datetime], PropertyInfo(alias="sendDate", format="iso8601")] @@ -142,6 +163,116 @@ class PostcardCreateWithTemplate(TypedDict, total=False): You can supply _either_ this or `frontHTML` but not both. """ + size: Required[Literal["6x4", "9x6", "11x6"]] + """Enum representing the supported postcard sizes.""" + + to: Required[PostcardCreateWithTemplateTo] + """The recipient of this order. + + You can either supply the contact information inline here or provide a contact + ID. PostGrid will automatically deduplicate contacts regardless of whether you + provide the information inline here or call the contact creation endpoint. + """ + + description: str + """An optional string describing this resource. + + Will be visible in the API and the dashboard. + """ + + from_: Annotated[PostcardCreateWithTemplateFrom, PropertyInfo(alias="from")] + """The contact information of the sender. + + You can pass contact information inline here just like you can for the `to`. + Unlike other order types, the sender address is optional for postcards. + """ + + mailing_class: Annotated[ + Literal[ + "first_class", + "standard_class", + "express", + "certified", + "certified_return_receipt", + "registered", + "usps_first_class", + "usps_standard_class", + "usps_eddm", + "usps_express_2_day", + "usps_express_3_day", + "usps_first_class_certified", + "usps_first_class_certified_return_receipt", + "usps_first_class_registered", + "usps_express_3_day_signature_confirmation", + "usps_express_3_day_certified", + "usps_express_3_day_certified_return_receipt", + "ca_post_lettermail", + "ca_post_personalized", + "ca_post_neighbourhood_mail", + "ups_express_overnight", + "ups_express_2_day", + "ups_express_3_day", + "royal_mail_first_class", + "royal_mail_second_class", + "au_post_second_class", + ], + PropertyInfo(alias="mailingClass"), + ] + """The mailing class of this order. + + If not provided, automatically set to `first_class`. + """ + + merge_variables: Annotated[Dict[str, object], PropertyInfo(alias="mergeVariables")] + """ + These will be merged with the variables in the template or HTML you create this + order with. The keys in this object should match the variable names in the + template _exactly_ as they are case-sensitive. Note that these _do not_ apply to + PDFs uploaded with the order. + """ + + metadata: Dict[str, object] + """See the section on Metadata.""" + + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + """Premium paper selection used for this postcard. + + Available values include: + + - `standard` + - `premium_paper_heavy_1_glossy` + - `premium_paper_postcard_uv_glossy_ss` + - `premium_paper_postcard_uv_glossy_ss_120lb` + - `premium_paper_postcard_satin_ds` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default postcard paper is used when configured; otherwise + `standard`. + """ + + send_date: Annotated[Union[str, datetime], PropertyInfo(alias="sendDate", format="iso8601")] + """This order will transition from `ready` to `printing` on the day after this + date. + + You can use this parameter to schedule orders for a future date. + """ + + +PostcardCreateWithTemplateTo: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] + +PostcardCreateWithTemplateFrom: TypeAlias = Union[ + ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str +] + class PostcardCreateWithPdfurl(TypedDict, total=False): pdf: Required[str] @@ -222,10 +353,29 @@ class PostcardCreateWithPdfurl(TypedDict, total=False): metadata: Dict[str, object] """See the section on Metadata.""" - paper: str - """Premium paper identifier. + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + """Premium paper selection used for this postcard. + + Available values include: - Use "standard" for regular stock or a premium*paper*\\** ID. + - `standard` + - `premium_paper_heavy_1_glossy` + - `premium_paper_postcard_uv_glossy_ss` + - `premium_paper_postcard_uv_glossy_ss_120lb` + - `premium_paper_postcard_satin_ds` + + Not all premium paper options are enabled for all organizations. If omitted, the + organization default postcard paper is used when configured; otherwise + `standard`. """ send_date: Annotated[Union[str, datetime], PropertyInfo(alias="sendDate", format="iso8601")] @@ -320,10 +470,29 @@ class PostcardCreateWithPdfFile(TypedDict, total=False): metadata: Dict[str, object] """See the section on Metadata.""" - paper: str - """Premium paper identifier. + paper: Union[ + Literal[ + "standard", + "premium_paper_heavy_1_glossy", + "premium_paper_postcard_uv_glossy_ss", + "premium_paper_postcard_uv_glossy_ss_120lb", + "premium_paper_postcard_satin_ds", + ], + str, + ] + """Premium paper selection used for this postcard. + + Available values include: + + - `standard` + - `premium_paper_heavy_1_glossy` + - `premium_paper_postcard_uv_glossy_ss` + - `premium_paper_postcard_uv_glossy_ss_120lb` + - `premium_paper_postcard_satin_ds` - Use "standard" for regular stock or a premium*paper*\\** ID. + Not all premium paper options are enabled for all organizations. If omitted, the + organization default postcard paper is used when configured; otherwise + `standard`. """ send_date: Annotated[Union[str, datetime], PropertyInfo(alias="sendDate", format="iso8601")] diff --git a/src/postgrid/types/print_mail/self_mailer_create_params.py b/src/postgrid/types/print_mail/self_mailer_create_params.py index 0bfe3ff..3aa282d 100644 --- a/src/postgrid/types/print_mail/self_mailer_create_params.py +++ b/src/postgrid/types/print_mail/self_mailer_create_params.py @@ -17,6 +17,8 @@ "SelfMailerCreateWithHTMLFrom", "SelfMailerCreateWithHTMLTo", "SelfMailerCreateWithTemplate", + "SelfMailerCreateWithTemplateFrom", + "SelfMailerCreateWithTemplateTo", "SelfMailerCreateWithPdfurl", "SelfMailerCreateWithPdfurlFrom", "SelfMailerCreateWithPdfurlTo", @@ -123,6 +125,12 @@ class SelfMailerCreateWithHTML(TypedDict, total=False): class SelfMailerCreateWithTemplate(TypedDict, total=False): + from_: Required[Annotated[SelfMailerCreateWithTemplateFrom, PropertyInfo(alias="from")]] + """The contact information of the sender. + + You can pass contact information inline here just like you can for the `to`. + """ + inside_template: Required[Annotated[str, PropertyInfo(alias="insideTemplate")]] """The template ID for the inside of the self-mailer. @@ -135,6 +143,86 @@ class SelfMailerCreateWithTemplate(TypedDict, total=False): You can supply _either_ this or `outsideHTML` but not both. """ + size: Required[Literal["8.5x11_bifold", "8.5x11_trifold", "9.5x16_trifold"]] + """Enum representing the supported self-mailer sizes.""" + + to: Required[SelfMailerCreateWithTemplateTo] + """The recipient of this order. + + You can either supply the contact information inline here or provide a contact + ID. PostGrid will automatically deduplicate contacts regardless of whether you + provide the information inline here or call the contact creation endpoint. + """ + + description: str + """An optional string describing this resource. + + Will be visible in the API and the dashboard. + """ + + mailing_class: Annotated[ + Literal[ + "first_class", + "standard_class", + "express", + "certified", + "certified_return_receipt", + "registered", + "usps_first_class", + "usps_standard_class", + "usps_eddm", + "usps_express_2_day", + "usps_express_3_day", + "usps_first_class_certified", + "usps_first_class_certified_return_receipt", + "usps_first_class_registered", + "usps_express_3_day_signature_confirmation", + "usps_express_3_day_certified", + "usps_express_3_day_certified_return_receipt", + "ca_post_lettermail", + "ca_post_personalized", + "ca_post_neighbourhood_mail", + "ups_express_overnight", + "ups_express_2_day", + "ups_express_3_day", + "royal_mail_first_class", + "royal_mail_second_class", + "au_post_second_class", + ], + PropertyInfo(alias="mailingClass"), + ] + """The mailing class of this order. + + If not provided, automatically set to `first_class`. + """ + + merge_variables: Annotated[Dict[str, object], PropertyInfo(alias="mergeVariables")] + """ + These will be merged with the variables in the template or HTML you create this + order with. The keys in this object should match the variable names in the + template _exactly_ as they are case-sensitive. Note that these _do not_ apply to + PDFs uploaded with the order. + """ + + metadata: Dict[str, object] + """See the section on Metadata.""" + + send_date: Annotated[Union[str, datetime], PropertyInfo(alias="sendDate", format="iso8601")] + """This order will transition from `ready` to `printing` on the day after this + date. + + You can use this parameter to schedule orders for a future date. + """ + + +SelfMailerCreateWithTemplateFrom: TypeAlias = Union[ + ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str +] + +SelfMailerCreateWithTemplateTo: TypeAlias = Union[ + ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str +] + class SelfMailerCreateWithPdfurl(TypedDict, total=False): from_: Required[Annotated[SelfMailerCreateWithPdfurlFrom, PropertyInfo(alias="from")]] diff --git a/tests/api_resources/print_mail/test_campaigns.py b/tests/api_resources/print_mail/test_campaigns.py index eb188b7..0b7db6e 100644 --- a/tests/api_resources/print_mail/test_campaigns.py +++ b/tests/api_resources/print_mail/test_campaigns.py @@ -68,6 +68,7 @@ def test_method_create_with_all_params(self, client: PostGrid) -> None: "mailing_class": "first_class", "merge_variables": {"foo": "bar"}, "metadata": {"foo": "string"}, + "paper": "standard", "pdf": "https://example.com", "perforated_page": 1, "return_envelope": "returnEnvelope", @@ -82,7 +83,7 @@ def test_method_create_with_all_params(self, client: PostGrid) -> None: "mailing_class": "first_class", "merge_variables": {"foo": "bar"}, "metadata": {"foo": "string"}, - "paper": "premium_paper_L6fw2k_N_j", + "paper": "standard", "pdf": "https://example.com", "size": "6x4", }, @@ -225,6 +226,7 @@ def test_method_update_with_all_params(self, client: PostGrid) -> None: "mailing_class": "first_class", "merge_variables": {"foo": "bar"}, "metadata": {"foo": "string"}, + "paper": "standard", "pdf": "https://example.com", "perforated_page": 1, "return_envelope": "returnEnvelope", @@ -240,7 +242,7 @@ def test_method_update_with_all_params(self, client: PostGrid) -> None: "mailing_class": "first_class", "merge_variables": {"foo": "bar"}, "metadata": {"foo": "string"}, - "paper": "premium_paper_L6fw2k_N_j", + "paper": "standard", "pdf": "https://example.com", "size": "6x4", }, @@ -484,6 +486,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncPostGrid) "mailing_class": "first_class", "merge_variables": {"foo": "bar"}, "metadata": {"foo": "string"}, + "paper": "standard", "pdf": "https://example.com", "perforated_page": 1, "return_envelope": "returnEnvelope", @@ -498,7 +501,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncPostGrid) "mailing_class": "first_class", "merge_variables": {"foo": "bar"}, "metadata": {"foo": "string"}, - "paper": "premium_paper_L6fw2k_N_j", + "paper": "standard", "pdf": "https://example.com", "size": "6x4", }, @@ -641,6 +644,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncPostGrid) "mailing_class": "first_class", "merge_variables": {"foo": "bar"}, "metadata": {"foo": "string"}, + "paper": "standard", "pdf": "https://example.com", "perforated_page": 1, "return_envelope": "returnEnvelope", @@ -656,7 +660,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncPostGrid) "mailing_class": "first_class", "merge_variables": {"foo": "bar"}, "metadata": {"foo": "string"}, - "paper": "premium_paper_L6fw2k_N_j", + "paper": "standard", "pdf": "https://example.com", "size": "6x4", }, diff --git a/tests/api_resources/print_mail/test_letters.py b/tests/api_resources/print_mail/test_letters.py index 8e266ce..c342b7f 100644 --- a/tests/api_resources/print_mail/test_letters.py +++ b/tests/api_resources/print_mail/test_letters.py @@ -93,6 +93,7 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non mailing_class="first_class", merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, + paper="standard", perforated_page=1, plastic_card={ "size": "standard", @@ -165,7 +166,93 @@ def test_streaming_response_create_overload_1(self, client: PostGrid) -> None: @parametrize def test_method_create_overload_2(self, client: PostGrid) -> None: letter = client.print_mail.letters.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, + template="template", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, + ) + assert_matches_type(Letter, letter, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> None: + letter = client.print_mail.letters.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + "address_line2": "addressLine2", + "city": "city", + "company_name": "companyName", + "description": "description", + "email": "email", + "force_verified_status": True, + "job_title": "jobTitle", + "last_name": "lastName", + "metadata": {"foo": "bar"}, + "phone_number": "phoneNumber", + "postal_or_zip": "postalOrZip", + "province_or_state": "provinceOrState", + "skip_verification": True, + }, template="template", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + "address_line2": "addressLine2", + "city": "city", + "company_name": "companyName", + "description": "description", + "email": "email", + "force_verified_status": True, + "job_title": "jobTitle", + "last_name": "lastName", + "metadata": {"foo": "bar"}, + "phone_number": "phoneNumber", + "postal_or_zip": "postalOrZip", + "province_or_state": "provinceOrState", + "skip_verification": True, + }, + address_placement="top_first_page", + attached_pdf={ + "file": "https://example.com", + "placement": "before_template", + }, + color=True, + description="description", + double_sided=True, + envelope="envelope", + mailing_class="first_class", + merge_variables={"foo": "bar"}, + metadata={"foo": "bar"}, + paper="standard", + perforated_page=1, + plastic_card={ + "size": "standard", + "double_sided": { + "back_html": "backHTML", + "back_template": "backTemplate", + "front_html": "frontHTML", + "front_template": "frontTemplate", + "pdf": "https://example.com", + }, + "single_sided": { + "html": "html", + "pdf": "https://example.com", + "template": "template", + }, + }, + return_envelope="returnEnvelope", + send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + size="us_letter", ) assert_matches_type(Letter, letter, path=["response"]) @@ -173,7 +260,17 @@ def test_method_create_overload_2(self, client: PostGrid) -> None: @parametrize def test_raw_response_create_overload_2(self, client: PostGrid) -> None: response = client.print_mail.letters.with_raw_response.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, template="template", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, ) assert response.is_closed is True @@ -185,7 +282,17 @@ def test_raw_response_create_overload_2(self, client: PostGrid) -> None: @parametrize def test_streaming_response_create_overload_2(self, client: PostGrid) -> None: with client.print_mail.letters.with_streaming_response.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, template="template", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -266,6 +373,7 @@ def test_method_create_with_all_params_overload_3(self, client: PostGrid) -> Non mailing_class="first_class", merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, + paper="standard", perforated_page=1, plastic_card={ "size": "standard", @@ -663,6 +771,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn mailing_class="first_class", merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, + paper="standard", perforated_page=1, plastic_card={ "size": "standard", @@ -735,7 +844,93 @@ async def test_streaming_response_create_overload_1(self, async_client: AsyncPos @parametrize async def test_method_create_overload_2(self, async_client: AsyncPostGrid) -> None: letter = await async_client.print_mail.letters.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, + template="template", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, + ) + assert_matches_type(Letter, letter, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_2(self, async_client: AsyncPostGrid) -> None: + letter = await async_client.print_mail.letters.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + "address_line2": "addressLine2", + "city": "city", + "company_name": "companyName", + "description": "description", + "email": "email", + "force_verified_status": True, + "job_title": "jobTitle", + "last_name": "lastName", + "metadata": {"foo": "bar"}, + "phone_number": "phoneNumber", + "postal_or_zip": "postalOrZip", + "province_or_state": "provinceOrState", + "skip_verification": True, + }, template="template", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + "address_line2": "addressLine2", + "city": "city", + "company_name": "companyName", + "description": "description", + "email": "email", + "force_verified_status": True, + "job_title": "jobTitle", + "last_name": "lastName", + "metadata": {"foo": "bar"}, + "phone_number": "phoneNumber", + "postal_or_zip": "postalOrZip", + "province_or_state": "provinceOrState", + "skip_verification": True, + }, + address_placement="top_first_page", + attached_pdf={ + "file": "https://example.com", + "placement": "before_template", + }, + color=True, + description="description", + double_sided=True, + envelope="envelope", + mailing_class="first_class", + merge_variables={"foo": "bar"}, + metadata={"foo": "bar"}, + paper="standard", + perforated_page=1, + plastic_card={ + "size": "standard", + "double_sided": { + "back_html": "backHTML", + "back_template": "backTemplate", + "front_html": "frontHTML", + "front_template": "frontTemplate", + "pdf": "https://example.com", + }, + "single_sided": { + "html": "html", + "pdf": "https://example.com", + "template": "template", + }, + }, + return_envelope="returnEnvelope", + send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + size="us_letter", ) assert_matches_type(Letter, letter, path=["response"]) @@ -743,7 +938,17 @@ async def test_method_create_overload_2(self, async_client: AsyncPostGrid) -> No @parametrize async def test_raw_response_create_overload_2(self, async_client: AsyncPostGrid) -> None: response = await async_client.print_mail.letters.with_raw_response.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, template="template", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, ) assert response.is_closed is True @@ -755,7 +960,17 @@ async def test_raw_response_create_overload_2(self, async_client: AsyncPostGrid) @parametrize async def test_streaming_response_create_overload_2(self, async_client: AsyncPostGrid) -> None: async with async_client.print_mail.letters.with_streaming_response.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, template="template", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -836,6 +1051,7 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn mailing_class="first_class", merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, + paper="standard", perforated_page=1, plastic_card={ "size": "standard", diff --git a/tests/api_resources/print_mail/test_postcards.py b/tests/api_resources/print_mail/test_postcards.py index fa3b112..9a177bb 100644 --- a/tests/api_resources/print_mail/test_postcards.py +++ b/tests/api_resources/print_mail/test_postcards.py @@ -84,7 +84,7 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non mailing_class="first_class", merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, - paper="premium_paper_L6fw2k_N_j", + paper="standard", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), ) assert_matches_type(Postcard, postcard, path=["response"]) @@ -135,6 +135,64 @@ def test_method_create_overload_2(self, client: PostGrid) -> None: postcard = client.print_mail.postcards.create( back_template="backTemplate", front_template="frontTemplate", + size="6x4", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, + ) + assert_matches_type(Postcard, postcard, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> None: + postcard = client.print_mail.postcards.create( + back_template="backTemplate", + front_template="frontTemplate", + size="6x4", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + "address_line2": "addressLine2", + "city": "city", + "company_name": "companyName", + "description": "description", + "email": "email", + "force_verified_status": True, + "job_title": "jobTitle", + "last_name": "lastName", + "metadata": {"foo": "bar"}, + "phone_number": "phoneNumber", + "postal_or_zip": "postalOrZip", + "province_or_state": "provinceOrState", + "skip_verification": True, + }, + description="description", + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + "address_line2": "addressLine2", + "city": "city", + "company_name": "companyName", + "description": "description", + "email": "email", + "force_verified_status": True, + "job_title": "jobTitle", + "last_name": "lastName", + "metadata": {"foo": "bar"}, + "phone_number": "phoneNumber", + "postal_or_zip": "postalOrZip", + "province_or_state": "provinceOrState", + "skip_verification": True, + }, + mailing_class="first_class", + merge_variables={"foo": "bar"}, + metadata={"foo": "bar"}, + paper="standard", + send_date=parse_datetime("2019-12-27T18:11:19.117Z"), ) assert_matches_type(Postcard, postcard, path=["response"]) @@ -144,6 +202,12 @@ def test_raw_response_create_overload_2(self, client: PostGrid) -> None: response = client.print_mail.postcards.with_raw_response.create( back_template="backTemplate", front_template="frontTemplate", + size="6x4", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, ) assert response.is_closed is True @@ -157,6 +221,12 @@ def test_streaming_response_create_overload_2(self, client: PostGrid) -> None: with client.print_mail.postcards.with_streaming_response.create( back_template="backTemplate", front_template="frontTemplate", + size="6x4", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -226,7 +296,7 @@ def test_method_create_with_all_params_overload_3(self, client: PostGrid) -> Non mailing_class="first_class", merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, - paper="premium_paper_L6fw2k_N_j", + paper="standard", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), ) assert_matches_type(Postcard, postcard, path=["response"]) @@ -329,7 +399,7 @@ def test_method_create_with_all_params_overload_4(self, client: PostGrid) -> Non mailing_class="first_class", merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, - paper="premium_paper_L6fw2k_N_j", + paper="standard", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), ) assert_matches_type(Postcard, postcard, path=["response"]) @@ -692,7 +762,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn mailing_class="first_class", merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, - paper="premium_paper_L6fw2k_N_j", + paper="standard", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), ) assert_matches_type(Postcard, postcard, path=["response"]) @@ -743,6 +813,64 @@ async def test_method_create_overload_2(self, async_client: AsyncPostGrid) -> No postcard = await async_client.print_mail.postcards.create( back_template="backTemplate", front_template="frontTemplate", + size="6x4", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, + ) + assert_matches_type(Postcard, postcard, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_2(self, async_client: AsyncPostGrid) -> None: + postcard = await async_client.print_mail.postcards.create( + back_template="backTemplate", + front_template="frontTemplate", + size="6x4", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + "address_line2": "addressLine2", + "city": "city", + "company_name": "companyName", + "description": "description", + "email": "email", + "force_verified_status": True, + "job_title": "jobTitle", + "last_name": "lastName", + "metadata": {"foo": "bar"}, + "phone_number": "phoneNumber", + "postal_or_zip": "postalOrZip", + "province_or_state": "provinceOrState", + "skip_verification": True, + }, + description="description", + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + "address_line2": "addressLine2", + "city": "city", + "company_name": "companyName", + "description": "description", + "email": "email", + "force_verified_status": True, + "job_title": "jobTitle", + "last_name": "lastName", + "metadata": {"foo": "bar"}, + "phone_number": "phoneNumber", + "postal_or_zip": "postalOrZip", + "province_or_state": "provinceOrState", + "skip_verification": True, + }, + mailing_class="first_class", + merge_variables={"foo": "bar"}, + metadata={"foo": "bar"}, + paper="standard", + send_date=parse_datetime("2019-12-27T18:11:19.117Z"), ) assert_matches_type(Postcard, postcard, path=["response"]) @@ -752,6 +880,12 @@ async def test_raw_response_create_overload_2(self, async_client: AsyncPostGrid) response = await async_client.print_mail.postcards.with_raw_response.create( back_template="backTemplate", front_template="frontTemplate", + size="6x4", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, ) assert response.is_closed is True @@ -765,6 +899,12 @@ async def test_streaming_response_create_overload_2(self, async_client: AsyncPos async with async_client.print_mail.postcards.with_streaming_response.create( back_template="backTemplate", front_template="frontTemplate", + size="6x4", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -834,7 +974,7 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn mailing_class="first_class", merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, - paper="premium_paper_L6fw2k_N_j", + paper="standard", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), ) assert_matches_type(Postcard, postcard, path=["response"]) @@ -937,7 +1077,7 @@ async def test_method_create_with_all_params_overload_4(self, async_client: Asyn mailing_class="first_class", merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, - paper="premium_paper_L6fw2k_N_j", + paper="standard", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), ) assert_matches_type(Postcard, postcard, path=["response"]) diff --git a/tests/api_resources/print_mail/test_self_mailers.py b/tests/api_resources/print_mail/test_self_mailers.py index f8755da..4746aa0 100644 --- a/tests/api_resources/print_mail/test_self_mailers.py +++ b/tests/api_resources/print_mail/test_self_mailers.py @@ -147,8 +147,70 @@ def test_streaming_response_create_overload_1(self, client: PostGrid) -> None: @parametrize def test_method_create_overload_2(self, client: PostGrid) -> None: self_mailer = client.print_mail.self_mailers.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, inside_template="insideTemplate", outside_template="outsideTemplate", + size="8.5x11_bifold", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, + ) + assert_matches_type(SelfMailer, self_mailer, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> None: + self_mailer = client.print_mail.self_mailers.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + "address_line2": "addressLine2", + "city": "city", + "company_name": "companyName", + "description": "description", + "email": "email", + "force_verified_status": True, + "job_title": "jobTitle", + "last_name": "lastName", + "metadata": {"foo": "bar"}, + "phone_number": "phoneNumber", + "postal_or_zip": "postalOrZip", + "province_or_state": "provinceOrState", + "skip_verification": True, + }, + inside_template="insideTemplate", + outside_template="outsideTemplate", + size="8.5x11_bifold", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + "address_line2": "addressLine2", + "city": "city", + "company_name": "companyName", + "description": "description", + "email": "email", + "force_verified_status": True, + "job_title": "jobTitle", + "last_name": "lastName", + "metadata": {"foo": "bar"}, + "phone_number": "phoneNumber", + "postal_or_zip": "postalOrZip", + "province_or_state": "provinceOrState", + "skip_verification": True, + }, + description="description", + mailing_class="first_class", + merge_variables={"foo": "bar"}, + metadata={"foo": "bar"}, + send_date=parse_datetime("2019-12-27T18:11:19.117Z"), ) assert_matches_type(SelfMailer, self_mailer, path=["response"]) @@ -156,8 +218,19 @@ def test_method_create_overload_2(self, client: PostGrid) -> None: @parametrize def test_raw_response_create_overload_2(self, client: PostGrid) -> None: response = client.print_mail.self_mailers.with_raw_response.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, inside_template="insideTemplate", outside_template="outsideTemplate", + size="8.5x11_bifold", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, ) assert response.is_closed is True @@ -169,8 +242,19 @@ def test_raw_response_create_overload_2(self, client: PostGrid) -> None: @parametrize def test_streaming_response_create_overload_2(self, client: PostGrid) -> None: with client.print_mail.self_mailers.with_streaming_response.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, inside_template="insideTemplate", outside_template="outsideTemplate", + size="8.5x11_bifold", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -751,8 +835,70 @@ async def test_streaming_response_create_overload_1(self, async_client: AsyncPos @parametrize async def test_method_create_overload_2(self, async_client: AsyncPostGrid) -> None: self_mailer = await async_client.print_mail.self_mailers.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, inside_template="insideTemplate", outside_template="outsideTemplate", + size="8.5x11_bifold", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, + ) + assert_matches_type(SelfMailer, self_mailer, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params_overload_2(self, async_client: AsyncPostGrid) -> None: + self_mailer = await async_client.print_mail.self_mailers.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + "address_line2": "addressLine2", + "city": "city", + "company_name": "companyName", + "description": "description", + "email": "email", + "force_verified_status": True, + "job_title": "jobTitle", + "last_name": "lastName", + "metadata": {"foo": "bar"}, + "phone_number": "phoneNumber", + "postal_or_zip": "postalOrZip", + "province_or_state": "provinceOrState", + "skip_verification": True, + }, + inside_template="insideTemplate", + outside_template="outsideTemplate", + size="8.5x11_bifold", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + "address_line2": "addressLine2", + "city": "city", + "company_name": "companyName", + "description": "description", + "email": "email", + "force_verified_status": True, + "job_title": "jobTitle", + "last_name": "lastName", + "metadata": {"foo": "bar"}, + "phone_number": "phoneNumber", + "postal_or_zip": "postalOrZip", + "province_or_state": "provinceOrState", + "skip_verification": True, + }, + description="description", + mailing_class="first_class", + merge_variables={"foo": "bar"}, + metadata={"foo": "bar"}, + send_date=parse_datetime("2019-12-27T18:11:19.117Z"), ) assert_matches_type(SelfMailer, self_mailer, path=["response"]) @@ -760,8 +906,19 @@ async def test_method_create_overload_2(self, async_client: AsyncPostGrid) -> No @parametrize async def test_raw_response_create_overload_2(self, async_client: AsyncPostGrid) -> None: response = await async_client.print_mail.self_mailers.with_raw_response.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, inside_template="insideTemplate", outside_template="outsideTemplate", + size="8.5x11_bifold", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, ) assert response.is_closed is True @@ -773,8 +930,19 @@ async def test_raw_response_create_overload_2(self, async_client: AsyncPostGrid) @parametrize async def test_streaming_response_create_overload_2(self, async_client: AsyncPostGrid) -> None: async with async_client.print_mail.self_mailers.with_streaming_response.create( + from_={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, inside_template="insideTemplate", outside_template="outsideTemplate", + size="8.5x11_bifold", + to={ + "address_line1": "addressLine1", + "country_code": "countryCode", + "first_name": "firstName", + }, ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" From 6472f0c67cae5d8946f43724d29f53762178918b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 17:38:37 +0000 Subject: [PATCH 4/7] feat(api): update api with events and webhook capabilities --- .stats.yml | 8 +- api.md | 29 + src/postgrid/resources/print_mail/__init__.py | 28 + src/postgrid/resources/print_mail/events.py | 255 +++++ .../resources/print_mail/print_mail.py | 238 +++++ src/postgrid/resources/print_mail/webhooks.py | 902 ++++++++++++++++++ src/postgrid/types/print_mail/__init__.py | 9 + src/postgrid/types/print_mail/event.py | 57 ++ .../types/print_mail/event_list_params.py | 38 + src/postgrid/types/print_mail/webhook.py | 74 ++ .../types/print_mail/webhook_create_params.py | 59 ++ .../print_mail/webhook_delete_response.py | 17 + .../types/print_mail/webhook_invocation.py | 62 ++ .../webhook_list_invocations_params.py | 22 + .../types/print_mail/webhook_list_params.py | 22 + .../types/print_mail/webhook_update_params.py | 60 ++ tests/api_resources/print_mail/test_events.py | 101 ++ .../api_resources/print_mail/test_webhooks.py | 593 ++++++++++++ 18 files changed, 2570 insertions(+), 4 deletions(-) create mode 100644 src/postgrid/resources/print_mail/events.py create mode 100644 src/postgrid/resources/print_mail/webhooks.py create mode 100644 src/postgrid/types/print_mail/event.py create mode 100644 src/postgrid/types/print_mail/event_list_params.py create mode 100644 src/postgrid/types/print_mail/webhook.py create mode 100644 src/postgrid/types/print_mail/webhook_create_params.py create mode 100644 src/postgrid/types/print_mail/webhook_delete_response.py create mode 100644 src/postgrid/types/print_mail/webhook_invocation.py create mode 100644 src/postgrid/types/print_mail/webhook_list_invocations_params.py create mode 100644 src/postgrid/types/print_mail/webhook_list_params.py create mode 100644 src/postgrid/types/print_mail/webhook_update_params.py create mode 100644 tests/api_resources/print_mail/test_events.py create mode 100644 tests/api_resources/print_mail/test_webhooks.py diff --git a/.stats.yml b/.stats.yml index beca239..dd2b394 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 119 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/postgrid/postgrid-d00ba06c82004a1a431d4c1992fc13c65ed4ffc6bb4dcd06f4b1e10037b1cf60.yml -openapi_spec_hash: 45820a4d38f466f15dcbff2d011b098f -config_hash: 4429a41bb9161a59679a1a95b1ec7053 +configured_endpoints: 126 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/postgrid/postgrid-01345c918ca89a9697dad4fb9ef469d65f00a9443bc1046fcda4ab08d9e9224d.yml +openapi_spec_hash: 2bffa15225d43f8f9ae6d6ea5dccc6b4 +config_hash: 174a107082cfb0cbf120e23621f4345c diff --git a/api.md b/api.md index 020ed5e..cdeb4cb 100644 --- a/api.md +++ b/api.md @@ -115,6 +115,35 @@ Methods: - client.print_mail.trackers.delete(id) -> TrackerDeleteResponse - client.print_mail.trackers.retrieve_visits(id, \*\*params) -> SyncSkipLimit[TrackerRetrieveVisitsResponse] +## Webhooks + +Types: + +```python +from postgrid.types.print_mail import Webhook, WebhookInvocation, WebhookDeleteResponse +``` + +Methods: + +- client.print_mail.webhooks.create(\*\*params) -> Webhook +- client.print_mail.webhooks.retrieve(id) -> Webhook +- client.print_mail.webhooks.update(id, \*\*params) -> Webhook +- client.print_mail.webhooks.list(\*\*params) -> SyncSkipLimit[Webhook] +- client.print_mail.webhooks.delete(id) -> WebhookDeleteResponse +- client.print_mail.webhooks.list_invocations(id, \*\*params) -> SyncSkipLimit[WebhookInvocation] + +## Events + +Types: + +```python +from postgrid.types.print_mail import Event +``` + +Methods: + +- client.print_mail.events.list(\*\*params) -> SyncSkipLimit[Event] + ## Letters Types: diff --git a/src/postgrid/resources/print_mail/__init__.py b/src/postgrid/resources/print_mail/__init__.py index 8ac29b0..610d7b6 100644 --- a/src/postgrid/resources/print_mail/__init__.py +++ b/src/postgrid/resources/print_mail/__init__.py @@ -8,6 +8,14 @@ BoxesResourceWithStreamingResponse, AsyncBoxesResourceWithStreamingResponse, ) +from .events import ( + EventsResource, + AsyncEventsResource, + EventsResourceWithRawResponse, + AsyncEventsResourceWithRawResponse, + EventsResourceWithStreamingResponse, + AsyncEventsResourceWithStreamingResponse, +) from .cheques import ( ChequesResource, AsyncChequesResource, @@ -48,6 +56,14 @@ TrackersResourceWithStreamingResponse, AsyncTrackersResourceWithStreamingResponse, ) +from .webhooks import ( + WebhooksResource, + AsyncWebhooksResource, + WebhooksResourceWithRawResponse, + AsyncWebhooksResourceWithRawResponse, + WebhooksResourceWithStreamingResponse, + AsyncWebhooksResourceWithStreamingResponse, +) from .campaigns import ( CampaignsResource, AsyncCampaignsResource, @@ -172,6 +188,18 @@ "AsyncTrackersResourceWithRawResponse", "TrackersResourceWithStreamingResponse", "AsyncTrackersResourceWithStreamingResponse", + "WebhooksResource", + "AsyncWebhooksResource", + "WebhooksResourceWithRawResponse", + "AsyncWebhooksResourceWithRawResponse", + "WebhooksResourceWithStreamingResponse", + "AsyncWebhooksResourceWithStreamingResponse", + "EventsResource", + "AsyncEventsResource", + "EventsResourceWithRawResponse", + "AsyncEventsResourceWithRawResponse", + "EventsResourceWithStreamingResponse", + "AsyncEventsResourceWithStreamingResponse", "LettersResource", "AsyncLettersResource", "LettersResourceWithRawResponse", diff --git a/src/postgrid/resources/print_mail/events.py b/src/postgrid/resources/print_mail/events.py new file mode 100644 index 0000000..36dece2 --- /dev/null +++ b/src/postgrid/resources/print_mail/events.py @@ -0,0 +1,255 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List +from typing_extensions import Literal + +import httpx + +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...pagination import SyncSkipLimit, AsyncSkipLimit +from ..._base_client import AsyncPaginator, make_request_options +from ...types.print_mail import event_list_params +from ...types.print_mail.event import Event + +__all__ = ["EventsResource", "AsyncEventsResource"] + + +class EventsResource(SyncAPIResource): + """View Events related to your orders. + + An event is created whenever a webhook is triggered. For example, if a webhook + is created that listens to `letter.updated` events and the delivery status of a + letter is updated, an event detailing the updated fields will get created. + """ + + @cached_property + def with_raw_response(self) -> EventsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/postgrid/postgrid-python#accessing-raw-response-data-eg-headers + """ + return EventsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> EventsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/postgrid/postgrid-python#with_streaming_response + """ + return EventsResourceWithStreamingResponse(self) + + def list( + self, + *, + limit: int | Omit = omit, + skip: int | Omit = omit, + type: List[ + Literal[ + "letter.created", + "letter.updated", + "postcard.created", + "postcard.updated", + "self_mailer.created", + "self_mailer.updated", + "cheque.created", + "cheque.updated", + "box.created", + "box.updated", + "snap_pack.created", + "snap_pack.updated", + "return_envelope_order.created", + "return_envelope_order.updated", + "tracker.visited", + "campaign.created", + "campaign.updated", + "virtual_mailbox_item.created", + ] + ] + | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SyncSkipLimit[Event]: + """ + Retrieve a paginated list of Events. + + Args: + type: An optional list of event types to filter the results by. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/print-mail/v1/events", + page=SyncSkipLimit[Event], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "skip": skip, + "type": type, + }, + event_list_params.EventListParams, + ), + ), + model=Event, + ) + + +class AsyncEventsResource(AsyncAPIResource): + """View Events related to your orders. + + An event is created whenever a webhook is triggered. For example, if a webhook + is created that listens to `letter.updated` events and the delivery status of a + letter is updated, an event detailing the updated fields will get created. + """ + + @cached_property + def with_raw_response(self) -> AsyncEventsResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/postgrid/postgrid-python#accessing-raw-response-data-eg-headers + """ + return AsyncEventsResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncEventsResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/postgrid/postgrid-python#with_streaming_response + """ + return AsyncEventsResourceWithStreamingResponse(self) + + def list( + self, + *, + limit: int | Omit = omit, + skip: int | Omit = omit, + type: List[ + Literal[ + "letter.created", + "letter.updated", + "postcard.created", + "postcard.updated", + "self_mailer.created", + "self_mailer.updated", + "cheque.created", + "cheque.updated", + "box.created", + "box.updated", + "snap_pack.created", + "snap_pack.updated", + "return_envelope_order.created", + "return_envelope_order.updated", + "tracker.visited", + "campaign.created", + "campaign.updated", + "virtual_mailbox_item.created", + ] + ] + | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncPaginator[Event, AsyncSkipLimit[Event]]: + """ + Retrieve a paginated list of Events. + + Args: + type: An optional list of event types to filter the results by. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/print-mail/v1/events", + page=AsyncSkipLimit[Event], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "skip": skip, + "type": type, + }, + event_list_params.EventListParams, + ), + ), + model=Event, + ) + + +class EventsResourceWithRawResponse: + def __init__(self, events: EventsResource) -> None: + self._events = events + + self.list = to_raw_response_wrapper( + events.list, + ) + + +class AsyncEventsResourceWithRawResponse: + def __init__(self, events: AsyncEventsResource) -> None: + self._events = events + + self.list = async_to_raw_response_wrapper( + events.list, + ) + + +class EventsResourceWithStreamingResponse: + def __init__(self, events: EventsResource) -> None: + self._events = events + + self.list = to_streamed_response_wrapper( + events.list, + ) + + +class AsyncEventsResourceWithStreamingResponse: + def __init__(self, events: AsyncEventsResource) -> None: + self._events = events + + self.list = async_to_streamed_response_wrapper( + events.list, + ) diff --git a/src/postgrid/resources/print_mail/print_mail.py b/src/postgrid/resources/print_mail/print_mail.py index e25edc4..d1b68bb 100644 --- a/src/postgrid/resources/print_mail/print_mail.py +++ b/src/postgrid/resources/print_mail/print_mail.py @@ -10,6 +10,14 @@ BoxesResourceWithStreamingResponse, AsyncBoxesResourceWithStreamingResponse, ) +from .events import ( + EventsResource, + AsyncEventsResource, + EventsResourceWithRawResponse, + AsyncEventsResourceWithRawResponse, + EventsResourceWithStreamingResponse, + AsyncEventsResourceWithStreamingResponse, +) from .cheques import ( ChequesResource, AsyncChequesResource, @@ -42,6 +50,14 @@ TrackersResourceWithStreamingResponse, AsyncTrackersResourceWithStreamingResponse, ) +from .webhooks import ( + WebhooksResource, + AsyncWebhooksResource, + WebhooksResourceWithRawResponse, + AsyncWebhooksResourceWithRawResponse, + WebhooksResourceWithStreamingResponse, + AsyncWebhooksResourceWithStreamingResponse, +) from ..._compat import cached_property from .campaigns import ( CampaignsResource, @@ -177,6 +193,43 @@ def trackers(self) -> TrackersResource: """ return TrackersResource(self._client) + @cached_property + def webhooks(self) -> WebhooksResource: + """Create and manage Webhooks. + + Webhooks can be used to notify your application when events occur in PostGrid. + For example, you may use a `letter.updated` webhook to receive a notification + when a letter has been processed for delivery. + + Every webhook has a `secret` and this is used to sign the payload of the event. + + You can choose what format you want the payload to be delivered in. By default, + the webhook payload will be delivered as a [JSON Web Token](https://jwt.io/). + When you receive the event, you can verify it using a JWT library available for + your particular language (using the HMAC SHA256 Algorithm). There are + [many](https://jwt.io/#libraries-io) off-the-shelf solutions you can use. + + You can alternatively choose to receive a JSON payload. In this case, you'll + also receive a `PostGrid-Signature` HTTP header along with the payload. + + You must respond with a `200` status from your webhook. Otherwise, PostGrid + will retry the webhook up to 3 times. First, after 1 hour, then 2 hours, then + 4 hours. We will also keep track of every invocation and its response status. + You can retrieve data about prior invocations using the webhook invocations + list endpoint below. + """ + return WebhooksResource(self._client) + + @cached_property + def events(self) -> EventsResource: + """View Events related to your orders. + + An event is created whenever a webhook is triggered. For example, if a webhook + is created that listens to `letter.updated` events and the delivery status of a + letter is updated, an event detailing the updated fields will get created. + """ + return EventsResource(self._client) + @cached_property def letters(self) -> LettersResource: return LettersResource(self._client) @@ -378,6 +431,43 @@ def trackers(self) -> AsyncTrackersResource: """ return AsyncTrackersResource(self._client) + @cached_property + def webhooks(self) -> AsyncWebhooksResource: + """Create and manage Webhooks. + + Webhooks can be used to notify your application when events occur in PostGrid. + For example, you may use a `letter.updated` webhook to receive a notification + when a letter has been processed for delivery. + + Every webhook has a `secret` and this is used to sign the payload of the event. + + You can choose what format you want the payload to be delivered in. By default, + the webhook payload will be delivered as a [JSON Web Token](https://jwt.io/). + When you receive the event, you can verify it using a JWT library available for + your particular language (using the HMAC SHA256 Algorithm). There are + [many](https://jwt.io/#libraries-io) off-the-shelf solutions you can use. + + You can alternatively choose to receive a JSON payload. In this case, you'll + also receive a `PostGrid-Signature` HTTP header along with the payload. + + You must respond with a `200` status from your webhook. Otherwise, PostGrid + will retry the webhook up to 3 times. First, after 1 hour, then 2 hours, then + 4 hours. We will also keep track of every invocation and its response status. + You can retrieve data about prior invocations using the webhook invocations + list endpoint below. + """ + return AsyncWebhooksResource(self._client) + + @cached_property + def events(self) -> AsyncEventsResource: + """View Events related to your orders. + + An event is created whenever a webhook is triggered. For example, if a webhook + is created that listens to `letter.updated` events and the delivery status of a + letter is updated, an event detailing the updated fields will get created. + """ + return AsyncEventsResource(self._client) + @cached_property def letters(self) -> AsyncLettersResource: return AsyncLettersResource(self._client) @@ -582,6 +672,43 @@ def trackers(self) -> TrackersResourceWithRawResponse: """ return TrackersResourceWithRawResponse(self._print_mail.trackers) + @cached_property + def webhooks(self) -> WebhooksResourceWithRawResponse: + """Create and manage Webhooks. + + Webhooks can be used to notify your application when events occur in PostGrid. + For example, you may use a `letter.updated` webhook to receive a notification + when a letter has been processed for delivery. + + Every webhook has a `secret` and this is used to sign the payload of the event. + + You can choose what format you want the payload to be delivered in. By default, + the webhook payload will be delivered as a [JSON Web Token](https://jwt.io/). + When you receive the event, you can verify it using a JWT library available for + your particular language (using the HMAC SHA256 Algorithm). There are + [many](https://jwt.io/#libraries-io) off-the-shelf solutions you can use. + + You can alternatively choose to receive a JSON payload. In this case, you'll + also receive a `PostGrid-Signature` HTTP header along with the payload. + + You must respond with a `200` status from your webhook. Otherwise, PostGrid + will retry the webhook up to 3 times. First, after 1 hour, then 2 hours, then + 4 hours. We will also keep track of every invocation and its response status. + You can retrieve data about prior invocations using the webhook invocations + list endpoint below. + """ + return WebhooksResourceWithRawResponse(self._print_mail.webhooks) + + @cached_property + def events(self) -> EventsResourceWithRawResponse: + """View Events related to your orders. + + An event is created whenever a webhook is triggered. For example, if a webhook + is created that listens to `letter.updated` events and the delivery status of a + letter is updated, an event detailing the updated fields will get created. + """ + return EventsResourceWithRawResponse(self._print_mail.events) + @cached_property def letters(self) -> LettersResourceWithRawResponse: return LettersResourceWithRawResponse(self._print_mail.letters) @@ -767,6 +894,43 @@ def trackers(self) -> AsyncTrackersResourceWithRawResponse: """ return AsyncTrackersResourceWithRawResponse(self._print_mail.trackers) + @cached_property + def webhooks(self) -> AsyncWebhooksResourceWithRawResponse: + """Create and manage Webhooks. + + Webhooks can be used to notify your application when events occur in PostGrid. + For example, you may use a `letter.updated` webhook to receive a notification + when a letter has been processed for delivery. + + Every webhook has a `secret` and this is used to sign the payload of the event. + + You can choose what format you want the payload to be delivered in. By default, + the webhook payload will be delivered as a [JSON Web Token](https://jwt.io/). + When you receive the event, you can verify it using a JWT library available for + your particular language (using the HMAC SHA256 Algorithm). There are + [many](https://jwt.io/#libraries-io) off-the-shelf solutions you can use. + + You can alternatively choose to receive a JSON payload. In this case, you'll + also receive a `PostGrid-Signature` HTTP header along with the payload. + + You must respond with a `200` status from your webhook. Otherwise, PostGrid + will retry the webhook up to 3 times. First, after 1 hour, then 2 hours, then + 4 hours. We will also keep track of every invocation and its response status. + You can retrieve data about prior invocations using the webhook invocations + list endpoint below. + """ + return AsyncWebhooksResourceWithRawResponse(self._print_mail.webhooks) + + @cached_property + def events(self) -> AsyncEventsResourceWithRawResponse: + """View Events related to your orders. + + An event is created whenever a webhook is triggered. For example, if a webhook + is created that listens to `letter.updated` events and the delivery status of a + letter is updated, an event detailing the updated fields will get created. + """ + return AsyncEventsResourceWithRawResponse(self._print_mail.events) + @cached_property def letters(self) -> AsyncLettersResourceWithRawResponse: return AsyncLettersResourceWithRawResponse(self._print_mail.letters) @@ -952,6 +1116,43 @@ def trackers(self) -> TrackersResourceWithStreamingResponse: """ return TrackersResourceWithStreamingResponse(self._print_mail.trackers) + @cached_property + def webhooks(self) -> WebhooksResourceWithStreamingResponse: + """Create and manage Webhooks. + + Webhooks can be used to notify your application when events occur in PostGrid. + For example, you may use a `letter.updated` webhook to receive a notification + when a letter has been processed for delivery. + + Every webhook has a `secret` and this is used to sign the payload of the event. + + You can choose what format you want the payload to be delivered in. By default, + the webhook payload will be delivered as a [JSON Web Token](https://jwt.io/). + When you receive the event, you can verify it using a JWT library available for + your particular language (using the HMAC SHA256 Algorithm). There are + [many](https://jwt.io/#libraries-io) off-the-shelf solutions you can use. + + You can alternatively choose to receive a JSON payload. In this case, you'll + also receive a `PostGrid-Signature` HTTP header along with the payload. + + You must respond with a `200` status from your webhook. Otherwise, PostGrid + will retry the webhook up to 3 times. First, after 1 hour, then 2 hours, then + 4 hours. We will also keep track of every invocation and its response status. + You can retrieve data about prior invocations using the webhook invocations + list endpoint below. + """ + return WebhooksResourceWithStreamingResponse(self._print_mail.webhooks) + + @cached_property + def events(self) -> EventsResourceWithStreamingResponse: + """View Events related to your orders. + + An event is created whenever a webhook is triggered. For example, if a webhook + is created that listens to `letter.updated` events and the delivery status of a + letter is updated, an event detailing the updated fields will get created. + """ + return EventsResourceWithStreamingResponse(self._print_mail.events) + @cached_property def letters(self) -> LettersResourceWithStreamingResponse: return LettersResourceWithStreamingResponse(self._print_mail.letters) @@ -1137,6 +1338,43 @@ def trackers(self) -> AsyncTrackersResourceWithStreamingResponse: """ return AsyncTrackersResourceWithStreamingResponse(self._print_mail.trackers) + @cached_property + def webhooks(self) -> AsyncWebhooksResourceWithStreamingResponse: + """Create and manage Webhooks. + + Webhooks can be used to notify your application when events occur in PostGrid. + For example, you may use a `letter.updated` webhook to receive a notification + when a letter has been processed for delivery. + + Every webhook has a `secret` and this is used to sign the payload of the event. + + You can choose what format you want the payload to be delivered in. By default, + the webhook payload will be delivered as a [JSON Web Token](https://jwt.io/). + When you receive the event, you can verify it using a JWT library available for + your particular language (using the HMAC SHA256 Algorithm). There are + [many](https://jwt.io/#libraries-io) off-the-shelf solutions you can use. + + You can alternatively choose to receive a JSON payload. In this case, you'll + also receive a `PostGrid-Signature` HTTP header along with the payload. + + You must respond with a `200` status from your webhook. Otherwise, PostGrid + will retry the webhook up to 3 times. First, after 1 hour, then 2 hours, then + 4 hours. We will also keep track of every invocation and its response status. + You can retrieve data about prior invocations using the webhook invocations + list endpoint below. + """ + return AsyncWebhooksResourceWithStreamingResponse(self._print_mail.webhooks) + + @cached_property + def events(self) -> AsyncEventsResourceWithStreamingResponse: + """View Events related to your orders. + + An event is created whenever a webhook is triggered. For example, if a webhook + is created that listens to `letter.updated` events and the delivery status of a + letter is updated, an event detailing the updated fields will get created. + """ + return AsyncEventsResourceWithStreamingResponse(self._print_mail.events) + @cached_property def letters(self) -> AsyncLettersResourceWithStreamingResponse: return AsyncLettersResourceWithStreamingResponse(self._print_mail.letters) diff --git a/src/postgrid/resources/print_mail/webhooks.py b/src/postgrid/resources/print_mail/webhooks.py new file mode 100644 index 0000000..17b5223 --- /dev/null +++ b/src/postgrid/resources/print_mail/webhooks.py @@ -0,0 +1,902 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, List +from typing_extensions import Literal + +import httpx + +from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._utils import path_template, maybe_transform, async_maybe_transform +from ..._compat import cached_property +from ..._resource import SyncAPIResource, AsyncAPIResource +from ..._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ...pagination import SyncSkipLimit, AsyncSkipLimit +from ..._base_client import AsyncPaginator, make_request_options +from ...types.print_mail import ( + webhook_list_params, + webhook_create_params, + webhook_update_params, + webhook_list_invocations_params, +) +from ...types.print_mail.webhook import Webhook +from ...types.print_mail.webhook_invocation import WebhookInvocation +from ...types.print_mail.webhook_delete_response import WebhookDeleteResponse + +__all__ = ["WebhooksResource", "AsyncWebhooksResource"] + + +class WebhooksResource(SyncAPIResource): + """Create and manage Webhooks. + + Webhooks can be used to notify your application when events occur in PostGrid. + For example, you may use a `letter.updated` webhook to receive a notification + when a letter has been processed for delivery. + + Every webhook has a `secret` and this is used to sign the payload of the event. + + You can choose what format you want the payload to be delivered in. By default, + the webhook payload will be delivered as a [JSON Web Token](https://jwt.io/). + When you receive the event, you can verify it using a JWT library available for + your particular language (using the HMAC SHA256 Algorithm). There are + [many](https://jwt.io/#libraries-io) off-the-shelf solutions you can use. + + You can alternatively choose to receive a JSON payload. In this case, you'll + also receive a `PostGrid-Signature` HTTP header along with the payload. + + You must respond with a `200` status from your webhook. Otherwise, PostGrid + will retry the webhook up to 3 times. First, after 1 hour, then 2 hours, then + 4 hours. We will also keep track of every invocation and its response status. + You can retrieve data about prior invocations using the webhook invocations + list endpoint below. + """ + + @cached_property + def with_raw_response(self) -> WebhooksResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/postgrid/postgrid-python#accessing-raw-response-data-eg-headers + """ + return WebhooksResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> WebhooksResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/postgrid/postgrid-python#with_streaming_response + """ + return WebhooksResourceWithStreamingResponse(self) + + def create( + self, + *, + enabled_events: List[ + Literal[ + "letter.created", + "letter.updated", + "postcard.created", + "postcard.updated", + "self_mailer.created", + "self_mailer.updated", + "cheque.created", + "cheque.updated", + "box.created", + "box.updated", + "snap_pack.created", + "snap_pack.updated", + "return_envelope_order.created", + "return_envelope_order.updated", + "tracker.visited", + "campaign.created", + "campaign.updated", + "virtual_mailbox_item.created", + ] + ], + url: str, + description: str | Omit = omit, + metadata: Dict[str, object] | Omit = omit, + payload_format: Literal["jwt", "json"] | Omit = omit, + secret: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Webhook: + """ + Create a Webhook. + + Args: + enabled_events: The list of event types this webhook listens for. + + url: An HTTPS URL that PostGrid can invoke for webhook deliveries. + + description: An optional string describing this resource. Will be visible in the API and the + dashboard. + + metadata: See the section on Metadata. + + payload_format: The format in which a Webhook's event payload is delivered. + + secret: A webhook signing secret with at least 20 non-whitespace characters. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._post( + "/print-mail/v1/webhooks", + body=maybe_transform( + { + "enabled_events": enabled_events, + "url": url, + "description": description, + "metadata": metadata, + "payload_format": payload_format, + "secret": secret, + }, + webhook_create_params.WebhookCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Webhook, + ) + + def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Webhook: + """ + Retrieve a Webhook by ID. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get( + path_template("/print-mail/v1/webhooks/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Webhook, + ) + + def update( + self, + id: str, + *, + description: str | Omit = omit, + enabled: bool | Omit = omit, + enabled_events: List[ + Literal[ + "letter.created", + "letter.updated", + "postcard.created", + "postcard.updated", + "self_mailer.created", + "self_mailer.updated", + "cheque.created", + "cheque.updated", + "box.created", + "box.updated", + "snap_pack.created", + "snap_pack.updated", + "return_envelope_order.created", + "return_envelope_order.updated", + "tracker.visited", + "campaign.created", + "campaign.updated", + "virtual_mailbox_item.created", + ] + ] + | Omit = omit, + metadata: Dict[str, object] | Omit = omit, + payload_format: Literal["jwt", "json"] | Omit = omit, + secret: str | Omit = omit, + url: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Webhook: + """ + Update a Webhook by ID. + + Args: + description: An optional string describing this resource. Will be visible in the API and the + dashboard. + + enabled: Whether this webhook is enabled. Disabled webhooks are not triggered. + + enabled_events: The list of event types this webhook listens for. + + metadata: See the section on Metadata. + + payload_format: The format in which a Webhook's event payload is delivered. + + secret: A webhook signing secret with at least 20 non-whitespace characters. + + url: An HTTPS URL that PostGrid can invoke for webhook deliveries. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._post( + path_template("/print-mail/v1/webhooks/{id}", id=id), + body=maybe_transform( + { + "description": description, + "enabled": enabled, + "enabled_events": enabled_events, + "metadata": metadata, + "payload_format": payload_format, + "secret": secret, + "url": url, + }, + webhook_update_params.WebhookUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Webhook, + ) + + def list( + self, + *, + limit: int | Omit = omit, + search: str | Omit = omit, + skip: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SyncSkipLimit[Webhook]: + """ + Retrieve a paginated list of Webhooks. + + Args: + search: You can supply any string to help narrow down the list of resources. For + example, if you pass `"New York"` (quoted), it will return resources that have + that string present somewhere in their response. Alternatively, you can supply a + structured search query. See the documentation on `StructuredSearchQuery` for + more details. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/print-mail/v1/webhooks", + page=SyncSkipLimit[Webhook], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "search": search, + "skip": skip, + }, + webhook_list_params.WebhookListParams, + ), + ), + model=Webhook, + ) + + def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> WebhookDeleteResponse: + """Delete a Webhook by ID. + + Note that this operation cannot be undone. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._delete( + path_template("/print-mail/v1/webhooks/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=WebhookDeleteResponse, + ) + + def list_invocations( + self, + id: str, + *, + limit: int | Omit = omit, + search: str | Omit = omit, + skip: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SyncSkipLimit[WebhookInvocation]: + """ + Retrieve a paginated list of invocations for a Webhook. + + Args: + search: You can supply any string to help narrow down the list of resources. For + example, if you pass `"New York"` (quoted), it will return resources that have + that string present somewhere in their response. Alternatively, you can supply a + structured search query. See the documentation on `StructuredSearchQuery` for + more details. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get_api_list( + path_template("/print-mail/v1/webhooks/{id}/invocations", id=id), + page=SyncSkipLimit[WebhookInvocation], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "search": search, + "skip": skip, + }, + webhook_list_invocations_params.WebhookListInvocationsParams, + ), + ), + model=WebhookInvocation, + ) + + +class AsyncWebhooksResource(AsyncAPIResource): + """Create and manage Webhooks. + + Webhooks can be used to notify your application when events occur in PostGrid. + For example, you may use a `letter.updated` webhook to receive a notification + when a letter has been processed for delivery. + + Every webhook has a `secret` and this is used to sign the payload of the event. + + You can choose what format you want the payload to be delivered in. By default, + the webhook payload will be delivered as a [JSON Web Token](https://jwt.io/). + When you receive the event, you can verify it using a JWT library available for + your particular language (using the HMAC SHA256 Algorithm). There are + [many](https://jwt.io/#libraries-io) off-the-shelf solutions you can use. + + You can alternatively choose to receive a JSON payload. In this case, you'll + also receive a `PostGrid-Signature` HTTP header along with the payload. + + You must respond with a `200` status from your webhook. Otherwise, PostGrid + will retry the webhook up to 3 times. First, after 1 hour, then 2 hours, then + 4 hours. We will also keep track of every invocation and its response status. + You can retrieve data about prior invocations using the webhook invocations + list endpoint below. + """ + + @cached_property + def with_raw_response(self) -> AsyncWebhooksResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/postgrid/postgrid-python#accessing-raw-response-data-eg-headers + """ + return AsyncWebhooksResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncWebhooksResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/postgrid/postgrid-python#with_streaming_response + """ + return AsyncWebhooksResourceWithStreamingResponse(self) + + async def create( + self, + *, + enabled_events: List[ + Literal[ + "letter.created", + "letter.updated", + "postcard.created", + "postcard.updated", + "self_mailer.created", + "self_mailer.updated", + "cheque.created", + "cheque.updated", + "box.created", + "box.updated", + "snap_pack.created", + "snap_pack.updated", + "return_envelope_order.created", + "return_envelope_order.updated", + "tracker.visited", + "campaign.created", + "campaign.updated", + "virtual_mailbox_item.created", + ] + ], + url: str, + description: str | Omit = omit, + metadata: Dict[str, object] | Omit = omit, + payload_format: Literal["jwt", "json"] | Omit = omit, + secret: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Webhook: + """ + Create a Webhook. + + Args: + enabled_events: The list of event types this webhook listens for. + + url: An HTTPS URL that PostGrid can invoke for webhook deliveries. + + description: An optional string describing this resource. Will be visible in the API and the + dashboard. + + metadata: See the section on Metadata. + + payload_format: The format in which a Webhook's event payload is delivered. + + secret: A webhook signing secret with at least 20 non-whitespace characters. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._post( + "/print-mail/v1/webhooks", + body=await async_maybe_transform( + { + "enabled_events": enabled_events, + "url": url, + "description": description, + "metadata": metadata, + "payload_format": payload_format, + "secret": secret, + }, + webhook_create_params.WebhookCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Webhook, + ) + + async def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Webhook: + """ + Retrieve a Webhook by ID. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._get( + path_template("/print-mail/v1/webhooks/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Webhook, + ) + + async def update( + self, + id: str, + *, + description: str | Omit = omit, + enabled: bool | Omit = omit, + enabled_events: List[ + Literal[ + "letter.created", + "letter.updated", + "postcard.created", + "postcard.updated", + "self_mailer.created", + "self_mailer.updated", + "cheque.created", + "cheque.updated", + "box.created", + "box.updated", + "snap_pack.created", + "snap_pack.updated", + "return_envelope_order.created", + "return_envelope_order.updated", + "tracker.visited", + "campaign.created", + "campaign.updated", + "virtual_mailbox_item.created", + ] + ] + | Omit = omit, + metadata: Dict[str, object] | Omit = omit, + payload_format: Literal["jwt", "json"] | Omit = omit, + secret: str | Omit = omit, + url: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> Webhook: + """ + Update a Webhook by ID. + + Args: + description: An optional string describing this resource. Will be visible in the API and the + dashboard. + + enabled: Whether this webhook is enabled. Disabled webhooks are not triggered. + + enabled_events: The list of event types this webhook listens for. + + metadata: See the section on Metadata. + + payload_format: The format in which a Webhook's event payload is delivered. + + secret: A webhook signing secret with at least 20 non-whitespace characters. + + url: An HTTPS URL that PostGrid can invoke for webhook deliveries. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._post( + path_template("/print-mail/v1/webhooks/{id}", id=id), + body=await async_maybe_transform( + { + "description": description, + "enabled": enabled, + "enabled_events": enabled_events, + "metadata": metadata, + "payload_format": payload_format, + "secret": secret, + "url": url, + }, + webhook_update_params.WebhookUpdateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=Webhook, + ) + + def list( + self, + *, + limit: int | Omit = omit, + search: str | Omit = omit, + skip: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncPaginator[Webhook, AsyncSkipLimit[Webhook]]: + """ + Retrieve a paginated list of Webhooks. + + Args: + search: You can supply any string to help narrow down the list of resources. For + example, if you pass `"New York"` (quoted), it will return resources that have + that string present somewhere in their response. Alternatively, you can supply a + structured search query. See the documentation on `StructuredSearchQuery` for + more details. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/print-mail/v1/webhooks", + page=AsyncSkipLimit[Webhook], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "search": search, + "skip": skip, + }, + webhook_list_params.WebhookListParams, + ), + ), + model=Webhook, + ) + + async def delete( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> WebhookDeleteResponse: + """Delete a Webhook by ID. + + Note that this operation cannot be undone. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._delete( + path_template("/print-mail/v1/webhooks/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=WebhookDeleteResponse, + ) + + def list_invocations( + self, + id: str, + *, + limit: int | Omit = omit, + search: str | Omit = omit, + skip: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncPaginator[WebhookInvocation, AsyncSkipLimit[WebhookInvocation]]: + """ + Retrieve a paginated list of invocations for a Webhook. + + Args: + search: You can supply any string to help narrow down the list of resources. For + example, if you pass `"New York"` (quoted), it will return resources that have + that string present somewhere in their response. Alternatively, you can supply a + structured search query. See the documentation on `StructuredSearchQuery` for + more details. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get_api_list( + path_template("/print-mail/v1/webhooks/{id}/invocations", id=id), + page=AsyncSkipLimit[WebhookInvocation], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "search": search, + "skip": skip, + }, + webhook_list_invocations_params.WebhookListInvocationsParams, + ), + ), + model=WebhookInvocation, + ) + + +class WebhooksResourceWithRawResponse: + def __init__(self, webhooks: WebhooksResource) -> None: + self._webhooks = webhooks + + self.create = to_raw_response_wrapper( + webhooks.create, + ) + self.retrieve = to_raw_response_wrapper( + webhooks.retrieve, + ) + self.update = to_raw_response_wrapper( + webhooks.update, + ) + self.list = to_raw_response_wrapper( + webhooks.list, + ) + self.delete = to_raw_response_wrapper( + webhooks.delete, + ) + self.list_invocations = to_raw_response_wrapper( + webhooks.list_invocations, + ) + + +class AsyncWebhooksResourceWithRawResponse: + def __init__(self, webhooks: AsyncWebhooksResource) -> None: + self._webhooks = webhooks + + self.create = async_to_raw_response_wrapper( + webhooks.create, + ) + self.retrieve = async_to_raw_response_wrapper( + webhooks.retrieve, + ) + self.update = async_to_raw_response_wrapper( + webhooks.update, + ) + self.list = async_to_raw_response_wrapper( + webhooks.list, + ) + self.delete = async_to_raw_response_wrapper( + webhooks.delete, + ) + self.list_invocations = async_to_raw_response_wrapper( + webhooks.list_invocations, + ) + + +class WebhooksResourceWithStreamingResponse: + def __init__(self, webhooks: WebhooksResource) -> None: + self._webhooks = webhooks + + self.create = to_streamed_response_wrapper( + webhooks.create, + ) + self.retrieve = to_streamed_response_wrapper( + webhooks.retrieve, + ) + self.update = to_streamed_response_wrapper( + webhooks.update, + ) + self.list = to_streamed_response_wrapper( + webhooks.list, + ) + self.delete = to_streamed_response_wrapper( + webhooks.delete, + ) + self.list_invocations = to_streamed_response_wrapper( + webhooks.list_invocations, + ) + + +class AsyncWebhooksResourceWithStreamingResponse: + def __init__(self, webhooks: AsyncWebhooksResource) -> None: + self._webhooks = webhooks + + self.create = async_to_streamed_response_wrapper( + webhooks.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + webhooks.retrieve, + ) + self.update = async_to_streamed_response_wrapper( + webhooks.update, + ) + self.list = async_to_streamed_response_wrapper( + webhooks.list, + ) + self.delete = async_to_streamed_response_wrapper( + webhooks.delete, + ) + self.list_invocations = async_to_streamed_response_wrapper( + webhooks.list_invocations, + ) diff --git a/src/postgrid/types/print_mail/__init__.py b/src/postgrid/types/print_mail/__init__.py index 58c4f51..509089b 100644 --- a/src/postgrid/types/print_mail/__init__.py +++ b/src/postgrid/types/print_mail/__init__.py @@ -2,10 +2,12 @@ from __future__ import annotations +from .event import Event as Event from .cheque import Cheque as Cheque from .letter import Letter as Letter from .report import Report as Report from .contact import Contact as Contact +from .webhook import Webhook as Webhook from .campaign import Campaign as Campaign from .postcard import Postcard as Postcard from .template import Template as Template @@ -25,17 +27,20 @@ from .box_create_params import BoxCreateParams as BoxCreateParams from .box_list_response import BoxListResponse as BoxListResponse from .email_preferences import EmailPreferences as EmailPreferences +from .event_list_params import EventListParams as EventListParams from .attached_pdf_param import AttachedPdfParam as AttachedPdfParam from .cheque_list_params import ChequeListParams as ChequeListParams from .digital_only_param import DigitalOnlyParam as DigitalOnlyParam from .letter_list_params import LetterListParams as LetterListParams from .plastic_card_param import PlasticCardParam as PlasticCardParam from .report_list_params import ReportListParams as ReportListParams +from .webhook_invocation import WebhookInvocation as WebhookInvocation from .box_create_response import BoxCreateResponse as BoxCreateResponse from .box_delete_response import BoxDeleteResponse as BoxDeleteResponse from .contact_list_params import ContactListParams as ContactListParams from .mailing_list_update import MailingListUpdate as MailingListUpdate from .tracker_list_params import TrackerListParams as TrackerListParams +from .webhook_list_params import WebhookListParams as WebhookListParams from .campaign_list_params import CampaignListParams as CampaignListParams from .campaign_send_params import CampaignSendParams as CampaignSendParams from .cheque_cancel_params import ChequeCancelParams as ChequeCancelParams @@ -54,6 +59,8 @@ from .tracker_create_params import TrackerCreateParams as TrackerCreateParams from .tracker_list_response import TrackerListResponse as TrackerListResponse from .tracker_update_params import TrackerUpdateParams as TrackerUpdateParams +from .webhook_create_params import WebhookCreateParams as WebhookCreateParams +from .webhook_update_params import WebhookUpdateParams as WebhookUpdateParams from .campaign_create_params import CampaignCreateParams as CampaignCreateParams from .campaign_update_params import CampaignUpdateParams as CampaignUpdateParams from .postcard_cancel_params import PostcardCancelParams as PostcardCancelParams @@ -67,6 +74,7 @@ from .tracker_create_response import TrackerCreateResponse as TrackerCreateResponse from .tracker_delete_response import TrackerDeleteResponse as TrackerDeleteResponse from .tracker_update_response import TrackerUpdateResponse as TrackerUpdateResponse +from .webhook_delete_response import WebhookDeleteResponse as WebhookDeleteResponse from .bank_account_list_params import BankAccountListParams as BankAccountListParams from .campaign_delete_response import CampaignDeleteResponse as CampaignDeleteResponse from .mailing_list_jobs_params import MailingListJobsParams as MailingListJobsParams @@ -99,6 +107,7 @@ from .snap_pack_progressions_response import SnapPackProgressionsResponse as SnapPackProgressionsResponse from .targeted_list_build_list_params import TargetedListBuildListParams as TargetedListBuildListParams from .virtual_mailbox_create_response import VirtualMailboxCreateResponse as VirtualMailboxCreateResponse +from .webhook_list_invocations_params import WebhookListInvocationsParams as WebhookListInvocationsParams from .sub_organization_create_response import SubOrganizationCreateResponse as SubOrganizationCreateResponse from .tracker_retrieve_visits_response import TrackerRetrieveVisitsResponse as TrackerRetrieveVisitsResponse from .mailing_list_import_create_params import MailingListImportCreateParams as MailingListImportCreateParams diff --git a/src/postgrid/types/print_mail/event.py b/src/postgrid/types/print_mail/event.py new file mode 100644 index 0000000..8fa34ec --- /dev/null +++ b/src/postgrid/types/print_mail/event.py @@ -0,0 +1,57 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import builtins +from typing import Dict, Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["Event"] + + +class Event(BaseModel): + id: str + """A unique ID prefixed with `event_`.""" + + created_at: datetime = FieldInfo(alias="createdAt") + """The UTC time at which this event was created.""" + + live: bool + """`true` if this is a live mode event else `false`.""" + + object: Literal["event"] + """Always `event`.""" + + type: Literal[ + "letter.created", + "letter.updated", + "postcard.created", + "postcard.updated", + "self_mailer.created", + "self_mailer.updated", + "cheque.created", + "cheque.updated", + "box.created", + "box.updated", + "snap_pack.created", + "snap_pack.updated", + "return_envelope_order.created", + "return_envelope_order.updated", + "tracker.visited", + "campaign.created", + "campaign.updated", + "virtual_mailbox_item.created", + ] + """The type of event that a Webhook can listen for and that an Event represents.""" + + data: Optional[Dict[str, builtins.object]] = None + """The data of the resource associated with this event.""" + + updated_fields: Optional[Dict[str, builtins.object]] = FieldInfo(alias="updatedFields", default=None) + """ + A record containing the updated fields of the resource associated with this + event. + """ diff --git a/src/postgrid/types/print_mail/event_list_params.py b/src/postgrid/types/print_mail/event_list_params.py new file mode 100644 index 0000000..9b30038 --- /dev/null +++ b/src/postgrid/types/print_mail/event_list_params.py @@ -0,0 +1,38 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List +from typing_extensions import Literal, TypedDict + +__all__ = ["EventListParams"] + + +class EventListParams(TypedDict, total=False): + limit: int + + skip: int + + type: List[ + Literal[ + "letter.created", + "letter.updated", + "postcard.created", + "postcard.updated", + "self_mailer.created", + "self_mailer.updated", + "cheque.created", + "cheque.updated", + "box.created", + "box.updated", + "snap_pack.created", + "snap_pack.updated", + "return_envelope_order.created", + "return_envelope_order.updated", + "tracker.visited", + "campaign.created", + "campaign.updated", + "virtual_mailbox_item.created", + ] + ] + """An optional list of event types to filter the results by.""" diff --git a/src/postgrid/types/print_mail/webhook.py b/src/postgrid/types/print_mail/webhook.py new file mode 100644 index 0000000..c853cd2 --- /dev/null +++ b/src/postgrid/types/print_mail/webhook.py @@ -0,0 +1,74 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import builtins +from typing import Dict, List, Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["Webhook"] + + +class Webhook(BaseModel): + id: str + """A unique ID prefixed with webhook\\__""" + + created_at: datetime = FieldInfo(alias="createdAt") + """The UTC time at which this resource was created.""" + + enabled: bool + """Whether this webhook is enabled. Disabled webhooks are not triggered.""" + + enabled_events: List[ + Literal[ + "letter.created", + "letter.updated", + "postcard.created", + "postcard.updated", + "self_mailer.created", + "self_mailer.updated", + "cheque.created", + "cheque.updated", + "box.created", + "box.updated", + "snap_pack.created", + "snap_pack.updated", + "return_envelope_order.created", + "return_envelope_order.updated", + "tracker.visited", + "campaign.created", + "campaign.updated", + "virtual_mailbox_item.created", + ] + ] = FieldInfo(alias="enabledEvents") + """The list of event types this webhook listens for.""" + + live: bool + """`true` if this is a live mode resource else `false`.""" + + object: Literal["webhook"] + """Always `webhook`.""" + + updated_at: datetime = FieldInfo(alias="updatedAt") + """The UTC time at which this resource was last updated.""" + + url: str + """An HTTPS URL that PostGrid can invoke for webhook deliveries.""" + + description: Optional[str] = None + """An optional string describing this resource. + + Will be visible in the API and the dashboard. + """ + + metadata: Optional[Dict[str, builtins.object]] = None + """See the section on Metadata.""" + + payload_format: Optional[Literal["jwt", "json"]] = FieldInfo(alias="payloadFormat", default=None) + """The format in which a Webhook's event payload is delivered.""" + + secret: Optional[str] = None + """A webhook signing secret with at least 20 non-whitespace characters.""" diff --git a/src/postgrid/types/print_mail/webhook_create_params.py b/src/postgrid/types/print_mail/webhook_create_params.py new file mode 100644 index 0000000..291373b --- /dev/null +++ b/src/postgrid/types/print_mail/webhook_create_params.py @@ -0,0 +1,59 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, List +from typing_extensions import Literal, Required, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["WebhookCreateParams"] + + +class WebhookCreateParams(TypedDict, total=False): + enabled_events: Required[ + Annotated[ + List[ + Literal[ + "letter.created", + "letter.updated", + "postcard.created", + "postcard.updated", + "self_mailer.created", + "self_mailer.updated", + "cheque.created", + "cheque.updated", + "box.created", + "box.updated", + "snap_pack.created", + "snap_pack.updated", + "return_envelope_order.created", + "return_envelope_order.updated", + "tracker.visited", + "campaign.created", + "campaign.updated", + "virtual_mailbox_item.created", + ] + ], + PropertyInfo(alias="enabledEvents"), + ] + ] + """The list of event types this webhook listens for.""" + + url: Required[str] + """An HTTPS URL that PostGrid can invoke for webhook deliveries.""" + + description: str + """An optional string describing this resource. + + Will be visible in the API and the dashboard. + """ + + metadata: Dict[str, object] + """See the section on Metadata.""" + + payload_format: Annotated[Literal["jwt", "json"], PropertyInfo(alias="payloadFormat")] + """The format in which a Webhook's event payload is delivered.""" + + secret: str + """A webhook signing secret with at least 20 non-whitespace characters.""" diff --git a/src/postgrid/types/print_mail/webhook_delete_response.py b/src/postgrid/types/print_mail/webhook_delete_response.py new file mode 100644 index 0000000..a359dd3 --- /dev/null +++ b/src/postgrid/types/print_mail/webhook_delete_response.py @@ -0,0 +1,17 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal + +from ..._models import BaseModel + +__all__ = ["WebhookDeleteResponse"] + + +class WebhookDeleteResponse(BaseModel): + id: str + """A unique ID prefixed with webhook\\__""" + + deleted: Literal[True] + + object: Literal["webhook"] + """Always `webhook`.""" diff --git a/src/postgrid/types/print_mail/webhook_invocation.py b/src/postgrid/types/print_mail/webhook_invocation.py new file mode 100644 index 0000000..3b112d5 --- /dev/null +++ b/src/postgrid/types/print_mail/webhook_invocation.py @@ -0,0 +1,62 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["WebhookInvocation"] + + +class WebhookInvocation(BaseModel): + id: str + """A unique ID prefixed with `webhook_invocation_`.""" + + created_at: datetime = FieldInfo(alias="createdAt") + """The UTC time at which this invocation was created.""" + + event: str + """The ID of the event that was delivered in this invocation.""" + + object: Literal["webhook_invocation"] + """Always `webhook_invocation`.""" + + status_code: int = FieldInfo(alias="statusCode") + """The HTTP status code returned by your endpoint for this invocation.""" + + type: Literal[ + "letter.created", + "letter.updated", + "postcard.created", + "postcard.updated", + "self_mailer.created", + "self_mailer.updated", + "cheque.created", + "cheque.updated", + "box.created", + "box.updated", + "snap_pack.created", + "snap_pack.updated", + "return_envelope_order.created", + "return_envelope_order.updated", + "tracker.visited", + "campaign.created", + "campaign.updated", + "virtual_mailbox_item.created", + ] + """The type of event that a Webhook can listen for and that an Event represents.""" + + updated_at: datetime = FieldInfo(alias="updatedAt") + """The UTC time at which this invocation was last updated.""" + + webhook: str + """The ID of the webhook that was invoked.""" + + order_id: Optional[str] = FieldInfo(alias="orderID", default=None) + """ + The ID of the order associated with this invocation, if the event was + order-related. + """ diff --git a/src/postgrid/types/print_mail/webhook_list_invocations_params.py b/src/postgrid/types/print_mail/webhook_list_invocations_params.py new file mode 100644 index 0000000..b478dfe --- /dev/null +++ b/src/postgrid/types/print_mail/webhook_list_invocations_params.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["WebhookListInvocationsParams"] + + +class WebhookListInvocationsParams(TypedDict, total=False): + limit: int + + search: str + """You can supply any string to help narrow down the list of resources. + + For example, if you pass `"New York"` (quoted), it will return resources that + have that string present somewhere in their response. Alternatively, you can + supply a structured search query. See the documentation on + `StructuredSearchQuery` for more details. + """ + + skip: int diff --git a/src/postgrid/types/print_mail/webhook_list_params.py b/src/postgrid/types/print_mail/webhook_list_params.py new file mode 100644 index 0000000..aeaee2c --- /dev/null +++ b/src/postgrid/types/print_mail/webhook_list_params.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["WebhookListParams"] + + +class WebhookListParams(TypedDict, total=False): + limit: int + + search: str + """You can supply any string to help narrow down the list of resources. + + For example, if you pass `"New York"` (quoted), it will return resources that + have that string present somewhere in their response. Alternatively, you can + supply a structured search query. See the documentation on + `StructuredSearchQuery` for more details. + """ + + skip: int diff --git a/src/postgrid/types/print_mail/webhook_update_params.py b/src/postgrid/types/print_mail/webhook_update_params.py new file mode 100644 index 0000000..4a0af36 --- /dev/null +++ b/src/postgrid/types/print_mail/webhook_update_params.py @@ -0,0 +1,60 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, List +from typing_extensions import Literal, Annotated, TypedDict + +from ..._utils import PropertyInfo + +__all__ = ["WebhookUpdateParams"] + + +class WebhookUpdateParams(TypedDict, total=False): + description: str + """An optional string describing this resource. + + Will be visible in the API and the dashboard. + """ + + enabled: bool + """Whether this webhook is enabled. Disabled webhooks are not triggered.""" + + enabled_events: Annotated[ + List[ + Literal[ + "letter.created", + "letter.updated", + "postcard.created", + "postcard.updated", + "self_mailer.created", + "self_mailer.updated", + "cheque.created", + "cheque.updated", + "box.created", + "box.updated", + "snap_pack.created", + "snap_pack.updated", + "return_envelope_order.created", + "return_envelope_order.updated", + "tracker.visited", + "campaign.created", + "campaign.updated", + "virtual_mailbox_item.created", + ] + ], + PropertyInfo(alias="enabledEvents"), + ] + """The list of event types this webhook listens for.""" + + metadata: Dict[str, object] + """See the section on Metadata.""" + + payload_format: Annotated[Literal["jwt", "json"], PropertyInfo(alias="payloadFormat")] + """The format in which a Webhook's event payload is delivered.""" + + secret: str + """A webhook signing secret with at least 20 non-whitespace characters.""" + + url: str + """An HTTPS URL that PostGrid can invoke for webhook deliveries.""" diff --git a/tests/api_resources/print_mail/test_events.py b/tests/api_resources/print_mail/test_events.py new file mode 100644 index 0000000..a6aff58 --- /dev/null +++ b/tests/api_resources/print_mail/test_events.py @@ -0,0 +1,101 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from postgrid import PostGrid, AsyncPostGrid +from tests.utils import assert_matches_type +from postgrid.pagination import SyncSkipLimit, AsyncSkipLimit +from postgrid.types.print_mail import Event + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestEvents: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: PostGrid) -> None: + event = client.print_mail.events.list() + assert_matches_type(SyncSkipLimit[Event], event, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: PostGrid) -> None: + event = client.print_mail.events.list( + limit=0, + skip=0, + type=["letter.created"], + ) + assert_matches_type(SyncSkipLimit[Event], event, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: PostGrid) -> None: + response = client.print_mail.events.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + event = response.parse() + assert_matches_type(SyncSkipLimit[Event], event, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: PostGrid) -> None: + with client.print_mail.events.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + event = response.parse() + assert_matches_type(SyncSkipLimit[Event], event, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncEvents: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncPostGrid) -> None: + event = await async_client.print_mail.events.list() + assert_matches_type(AsyncSkipLimit[Event], event, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncPostGrid) -> None: + event = await async_client.print_mail.events.list( + limit=0, + skip=0, + type=["letter.created"], + ) + assert_matches_type(AsyncSkipLimit[Event], event, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.events.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + event = await response.parse() + assert_matches_type(AsyncSkipLimit[Event], event, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.events.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + event = await response.parse() + assert_matches_type(AsyncSkipLimit[Event], event, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/print_mail/test_webhooks.py b/tests/api_resources/print_mail/test_webhooks.py new file mode 100644 index 0000000..cc0d709 --- /dev/null +++ b/tests/api_resources/print_mail/test_webhooks.py @@ -0,0 +1,593 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from postgrid import PostGrid, AsyncPostGrid +from tests.utils import assert_matches_type +from postgrid.pagination import SyncSkipLimit, AsyncSkipLimit +from postgrid.types.print_mail import ( + Webhook, + WebhookInvocation, + WebhookDeleteResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestWebhooks: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create(self, client: PostGrid) -> None: + webhook = client.print_mail.webhooks.create( + enabled_events=["letter.created"], + url="https://example.com/postgrid-webhook", + ) + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: PostGrid) -> None: + webhook = client.print_mail.webhooks.create( + enabled_events=["letter.created"], + url="https://example.com/postgrid-webhook", + description="Letter Created", + metadata={"foo": "bar"}, + payload_format="jwt", + secret="xxxxxxxxxxxxxxxxxxxx", + ) + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_create(self, client: PostGrid) -> None: + response = client.print_mail.webhooks.with_raw_response.create( + enabled_events=["letter.created"], + url="https://example.com/postgrid-webhook", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + webhook = response.parse() + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_create(self, client: PostGrid) -> None: + with client.print_mail.webhooks.with_streaming_response.create( + enabled_events=["letter.created"], + url="https://example.com/postgrid-webhook", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + webhook = response.parse() + assert_matches_type(Webhook, webhook, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve(self, client: PostGrid) -> None: + webhook = client.print_mail.webhooks.retrieve( + "id", + ) + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: PostGrid) -> None: + response = client.print_mail.webhooks.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + webhook = response.parse() + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: PostGrid) -> None: + with client.print_mail.webhooks.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + webhook = response.parse() + assert_matches_type(Webhook, webhook, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: PostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.print_mail.webhooks.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update(self, client: PostGrid) -> None: + webhook = client.print_mail.webhooks.update( + id="id", + ) + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_update_with_all_params(self, client: PostGrid) -> None: + webhook = client.print_mail.webhooks.update( + id="id", + description="Letter creates and updates", + enabled=True, + enabled_events=["letter.created", "letter.updated"], + metadata={"foo": "bar"}, + payload_format="jwt", + secret="xxxxxxxxxxxxxxxxxxxx", + url="https://example.com/postgrid-webhook", + ) + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_update(self, client: PostGrid) -> None: + response = client.print_mail.webhooks.with_raw_response.update( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + webhook = response.parse() + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_update(self, client: PostGrid) -> None: + with client.print_mail.webhooks.with_streaming_response.update( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + webhook = response.parse() + assert_matches_type(Webhook, webhook, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_update(self, client: PostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.print_mail.webhooks.with_raw_response.update( + id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: PostGrid) -> None: + webhook = client.print_mail.webhooks.list() + assert_matches_type(SyncSkipLimit[Webhook], webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: PostGrid) -> None: + webhook = client.print_mail.webhooks.list( + limit=0, + search="search", + skip=0, + ) + assert_matches_type(SyncSkipLimit[Webhook], webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: PostGrid) -> None: + response = client.print_mail.webhooks.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + webhook = response.parse() + assert_matches_type(SyncSkipLimit[Webhook], webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: PostGrid) -> None: + with client.print_mail.webhooks.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + webhook = response.parse() + assert_matches_type(SyncSkipLimit[Webhook], webhook, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_delete(self, client: PostGrid) -> None: + webhook = client.print_mail.webhooks.delete( + "id", + ) + assert_matches_type(WebhookDeleteResponse, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_delete(self, client: PostGrid) -> None: + response = client.print_mail.webhooks.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + webhook = response.parse() + assert_matches_type(WebhookDeleteResponse, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_delete(self, client: PostGrid) -> None: + with client.print_mail.webhooks.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + webhook = response.parse() + assert_matches_type(WebhookDeleteResponse, webhook, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_delete(self, client: PostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.print_mail.webhooks.with_raw_response.delete( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_invocations(self, client: PostGrid) -> None: + webhook = client.print_mail.webhooks.list_invocations( + id="id", + ) + assert_matches_type(SyncSkipLimit[WebhookInvocation], webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_invocations_with_all_params(self, client: PostGrid) -> None: + webhook = client.print_mail.webhooks.list_invocations( + id="id", + limit=0, + search="search", + skip=0, + ) + assert_matches_type(SyncSkipLimit[WebhookInvocation], webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list_invocations(self, client: PostGrid) -> None: + response = client.print_mail.webhooks.with_raw_response.list_invocations( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + webhook = response.parse() + assert_matches_type(SyncSkipLimit[WebhookInvocation], webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list_invocations(self, client: PostGrid) -> None: + with client.print_mail.webhooks.with_streaming_response.list_invocations( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + webhook = response.parse() + assert_matches_type(SyncSkipLimit[WebhookInvocation], webhook, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_list_invocations(self, client: PostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.print_mail.webhooks.with_raw_response.list_invocations( + id="", + ) + + +class TestAsyncWebhooks: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncPostGrid) -> None: + webhook = await async_client.print_mail.webhooks.create( + enabled_events=["letter.created"], + url="https://example.com/postgrid-webhook", + ) + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncPostGrid) -> None: + webhook = await async_client.print_mail.webhooks.create( + enabled_events=["letter.created"], + url="https://example.com/postgrid-webhook", + description="Letter Created", + metadata={"foo": "bar"}, + payload_format="jwt", + secret="xxxxxxxxxxxxxxxxxxxx", + ) + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.webhooks.with_raw_response.create( + enabled_events=["letter.created"], + url="https://example.com/postgrid-webhook", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + webhook = await response.parse() + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.webhooks.with_streaming_response.create( + enabled_events=["letter.created"], + url="https://example.com/postgrid-webhook", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + webhook = await response.parse() + assert_matches_type(Webhook, webhook, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncPostGrid) -> None: + webhook = await async_client.print_mail.webhooks.retrieve( + "id", + ) + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.webhooks.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + webhook = await response.parse() + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.webhooks.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + webhook = await response.parse() + assert_matches_type(Webhook, webhook, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncPostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.print_mail.webhooks.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update(self, async_client: AsyncPostGrid) -> None: + webhook = await async_client.print_mail.webhooks.update( + id="id", + ) + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_update_with_all_params(self, async_client: AsyncPostGrid) -> None: + webhook = await async_client.print_mail.webhooks.update( + id="id", + description="Letter creates and updates", + enabled=True, + enabled_events=["letter.created", "letter.updated"], + metadata={"foo": "bar"}, + payload_format="jwt", + secret="xxxxxxxxxxxxxxxxxxxx", + url="https://example.com/postgrid-webhook", + ) + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_update(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.webhooks.with_raw_response.update( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + webhook = await response.parse() + assert_matches_type(Webhook, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_update(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.webhooks.with_streaming_response.update( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + webhook = await response.parse() + assert_matches_type(Webhook, webhook, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_update(self, async_client: AsyncPostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.print_mail.webhooks.with_raw_response.update( + id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncPostGrid) -> None: + webhook = await async_client.print_mail.webhooks.list() + assert_matches_type(AsyncSkipLimit[Webhook], webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncPostGrid) -> None: + webhook = await async_client.print_mail.webhooks.list( + limit=0, + search="search", + skip=0, + ) + assert_matches_type(AsyncSkipLimit[Webhook], webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.webhooks.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + webhook = await response.parse() + assert_matches_type(AsyncSkipLimit[Webhook], webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.webhooks.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + webhook = await response.parse() + assert_matches_type(AsyncSkipLimit[Webhook], webhook, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_delete(self, async_client: AsyncPostGrid) -> None: + webhook = await async_client.print_mail.webhooks.delete( + "id", + ) + assert_matches_type(WebhookDeleteResponse, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_delete(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.webhooks.with_raw_response.delete( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + webhook = await response.parse() + assert_matches_type(WebhookDeleteResponse, webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_delete(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.webhooks.with_streaming_response.delete( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + webhook = await response.parse() + assert_matches_type(WebhookDeleteResponse, webhook, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_delete(self, async_client: AsyncPostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.print_mail.webhooks.with_raw_response.delete( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_invocations(self, async_client: AsyncPostGrid) -> None: + webhook = await async_client.print_mail.webhooks.list_invocations( + id="id", + ) + assert_matches_type(AsyncSkipLimit[WebhookInvocation], webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_invocations_with_all_params(self, async_client: AsyncPostGrid) -> None: + webhook = await async_client.print_mail.webhooks.list_invocations( + id="id", + limit=0, + search="search", + skip=0, + ) + assert_matches_type(AsyncSkipLimit[WebhookInvocation], webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list_invocations(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.webhooks.with_raw_response.list_invocations( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + webhook = await response.parse() + assert_matches_type(AsyncSkipLimit[WebhookInvocation], webhook, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list_invocations(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.webhooks.with_streaming_response.list_invocations( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + webhook = await response.parse() + assert_matches_type(AsyncSkipLimit[WebhookInvocation], webhook, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_list_invocations(self, async_client: AsyncPostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.print_mail.webhooks.with_raw_response.list_invocations( + id="", + ) From c8be87f4cfc054bc31b63e3dd1ab59183664801c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 05:51:04 +0000 Subject: [PATCH 5/7] feat: New endpoints, fixed and aligned schemas --- .stats.yml | 8 +- README.md | 19 + api.md | 49 ++ src/postgrid/_client.py | 147 +++- src/postgrid/_files.py | 2 +- src/postgrid/resources/__init__.py | 14 + .../resources/address_verification.py | 14 +- src/postgrid/resources/bulk_verification.py | 494 +++++++++++++ .../resources/intl_address_verification.py | 60 +- src/postgrid/resources/print_mail/__init__.py | 14 + .../resources/print_mail/bank_accounts.py | 40 ++ src/postgrid/resources/print_mail/boxes.py | 4 + src/postgrid/resources/print_mail/cheques.py | 74 +- src/postgrid/resources/print_mail/contacts.py | 64 ++ src/postgrid/resources/print_mail/letters.py | 4 + .../resources/print_mail/postcards.py | 4 + .../resources/print_mail/print_mail.py | 278 ++++++++ .../print_mail/return_envelopes/__init__.py | 33 + .../print_mail/return_envelopes/orders.py | 652 ++++++++++++++++++ .../return_envelopes/return_envelopes.py | 520 ++++++++++++++ .../resources/print_mail/self_mailers.py | 4 + .../resources/print_mail/templates.py | 14 + src/postgrid/types/__init__.py | 6 + ...s_verification_get_lookup_info_response.py | 3 + src/postgrid/types/addver_list.py | 170 +++++ .../types/bulk_verification_list_params.py | 15 + .../types/bulk_verification_list_response.py | 28 + .../bulk_verification_retrieve_response.py | 20 + .../types/bulk_verification_upload_params.py | 105 +++ .../bulk_verification_upload_response.py | 20 + ...autocomplete_advanced_previews_response.py | 6 +- ...tion_get_autocomplete_previews_response.py | 6 +- src/postgrid/types/print_mail/__init__.py | 3 + src/postgrid/types/print_mail/cheque.py | 24 +- .../types/print_mail/cheque_create_params.py | 42 +- src/postgrid/types/print_mail/contact.py | 7 + .../types/print_mail/contact_create_params.py | 14 + .../contact_create_with_company_name_param.py | 7 + .../contact_create_with_first_name_param.py | 7 + src/postgrid/types/print_mail/digital_only.py | 23 +- .../types/print_mail/digital_only_param.py | 21 +- .../types/print_mail/return_envelope.py | 137 ++++ .../return_envelope_create_params.py | 34 + .../print_mail/return_envelope_list_params.py | 22 + .../print_mail/return_envelopes/__init__.py | 9 + .../return_envelopes/order_cancel_params.py | 18 + .../return_envelopes/order_create_params.py | 24 + .../return_envelopes/order_list_params.py | 22 + .../return_envelopes/order_retrieve_params.py | 18 + .../return_envelopes/return_envelope_order.py | 60 ++ .../print_mail/return_envelopes/__init__.py | 1 + .../return_envelopes/test_orders.py | 599 ++++++++++++++++ .../api_resources/print_mail/test_cheques.py | 26 +- .../api_resources/print_mail/test_contacts.py | 4 + .../api_resources/print_mail/test_letters.py | 12 + .../print_mail/test_postcards.py | 16 + .../print_mail/test_return_envelopes.py | 275 ++++++++ .../print_mail/test_self_mailers.py | 16 + .../print_mail/test_snap_packs.py | 12 + tests/api_resources/test_bulk_verification.py | 318 +++++++++ 60 files changed, 4610 insertions(+), 52 deletions(-) create mode 100644 src/postgrid/resources/bulk_verification.py create mode 100644 src/postgrid/resources/print_mail/return_envelopes/__init__.py create mode 100644 src/postgrid/resources/print_mail/return_envelopes/orders.py create mode 100644 src/postgrid/resources/print_mail/return_envelopes/return_envelopes.py create mode 100644 src/postgrid/types/addver_list.py create mode 100644 src/postgrid/types/bulk_verification_list_params.py create mode 100644 src/postgrid/types/bulk_verification_list_response.py create mode 100644 src/postgrid/types/bulk_verification_retrieve_response.py create mode 100644 src/postgrid/types/bulk_verification_upload_params.py create mode 100644 src/postgrid/types/bulk_verification_upload_response.py create mode 100644 src/postgrid/types/print_mail/return_envelope.py create mode 100644 src/postgrid/types/print_mail/return_envelope_create_params.py create mode 100644 src/postgrid/types/print_mail/return_envelope_list_params.py create mode 100644 src/postgrid/types/print_mail/return_envelopes/__init__.py create mode 100644 src/postgrid/types/print_mail/return_envelopes/order_cancel_params.py create mode 100644 src/postgrid/types/print_mail/return_envelopes/order_create_params.py create mode 100644 src/postgrid/types/print_mail/return_envelopes/order_list_params.py create mode 100644 src/postgrid/types/print_mail/return_envelopes/order_retrieve_params.py create mode 100644 src/postgrid/types/print_mail/return_envelopes/return_envelope_order.py create mode 100644 tests/api_resources/print_mail/return_envelopes/__init__.py create mode 100644 tests/api_resources/print_mail/return_envelopes/test_orders.py create mode 100644 tests/api_resources/print_mail/test_return_envelopes.py create mode 100644 tests/api_resources/test_bulk_verification.py diff --git a/.stats.yml b/.stats.yml index dd2b394..86116e6 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 126 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/postgrid/postgrid-01345c918ca89a9697dad4fb9ef469d65f00a9443bc1046fcda4ab08d9e9224d.yml -openapi_spec_hash: 2bffa15225d43f8f9ae6d6ea5dccc6b4 -config_hash: 174a107082cfb0cbf120e23621f4345c +configured_endpoints: 137 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/postgrid/postgrid-32126b0df875e75e2a33a809e6fc25ea55cedc0d2505450361e71f4f2cedecf3.yml +openapi_spec_hash: 2cc8c911382f942c07b624e45c8db026 +config_hash: 6398155ff41b9bcbc09dc6066a1bf113 diff --git a/README.md b/README.md index 3365b96..ad1748d 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,25 @@ response = client.address_verification.verify( print(response.address) ``` +## File uploads + +Request parameters that correspond to file uploads can be passed as `bytes`, or a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`. + +```python +from pathlib import Path +from postgrid import PostGrid + +client = PostGrid() + +client.bulk_verification.upload( + file=Path("/path/to/file"), + mappings={"line1": "line1"}, + name="name", +) +``` + +The async client uses the exact same interface. If you pass a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance, the file contents will be read asynchronously automatically. + ## Handling errors When the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `postgrid.APIConnectionError` is raised. diff --git a/api.md b/api.md index cdeb4cb..39148f0 100644 --- a/api.md +++ b/api.md @@ -52,6 +52,25 @@ Methods: - client.intl_address_verification.get_autocomplete_previews(\*\*params) -> IntlAddressVerificationGetAutocompletePreviewsResponse - client.intl_address_verification.verify(\*\*params) -> IntlAddressVerificationVerifyResponse +# BulkVerification + +Types: + +```python +from postgrid.types import ( + AddverList, + BulkVerificationRetrieveResponse, + BulkVerificationListResponse, + BulkVerificationUploadResponse, +) +``` + +Methods: + +- client.bulk_verification.retrieve(id) -> BulkVerificationRetrieveResponse +- client.bulk_verification.list(\*\*params) -> BulkVerificationListResponse +- client.bulk_verification.upload(\*\*params) -> BulkVerificationUploadResponse + # PrintMail ## Contacts @@ -238,6 +257,36 @@ Methods: - client.print_mail.self_mailers.progress(id) -> SelfMailer - client.print_mail.self_mailers.retrieve_url(id) -> SelfMailerRetrieveURLResponse +## ReturnEnvelopes + +Types: + +```python +from postgrid.types.print_mail import ReturnEnvelope +``` + +Methods: + +- client.print_mail.return_envelopes.create(\*\*params) -> ReturnEnvelope +- client.print_mail.return_envelopes.retrieve(id) -> ReturnEnvelope +- client.print_mail.return_envelopes.list(\*\*params) -> SyncSkipLimit[ReturnEnvelope] + +### Orders + +Types: + +```python +from postgrid.types.print_mail.return_envelopes import ReturnEnvelopeOrder +``` + +Methods: + +- client.print_mail.return_envelopes.orders.create(id, \*\*params) -> ReturnEnvelopeOrder +- client.print_mail.return_envelopes.orders.retrieve(order_id, \*, id, \*\*params) -> ReturnEnvelopeOrder +- client.print_mail.return_envelopes.orders.list(id, \*\*params) -> SyncSkipLimit[ReturnEnvelopeOrder] +- client.print_mail.return_envelopes.orders.cancel(order_id, \*, id, \*\*params) -> ReturnEnvelopeOrder +- client.print_mail.return_envelopes.orders.fill(order_id, \*, id) -> ReturnEnvelopeOrder + ## Campaigns Types: diff --git a/src/postgrid/_client.py b/src/postgrid/_client.py index 873c587..a53a4fb 100644 --- a/src/postgrid/_client.py +++ b/src/postgrid/_client.py @@ -36,7 +36,8 @@ ) if TYPE_CHECKING: - from .resources import print_mail, address_verification, intl_address_verification + from .resources import print_mail, bulk_verification, address_verification, intl_address_verification + from .resources.bulk_verification import BulkVerificationResource, AsyncBulkVerificationResource from .resources.address_verification import AddressVerificationResource, AsyncAddressVerificationResource from .resources.print_mail.print_mail import PrintMailResource, AsyncPrintMailResource from .resources.intl_address_verification import ( @@ -148,6 +149,30 @@ def intl_address_verification(self) -> IntlAddressVerificationResource: return IntlAddressVerificationResource(self) + @cached_property + def bulk_verification(self) -> BulkVerificationResource: + """ + **Note: For verifying batches of addresses in real-time via JSON, please use + the "Batch Verify Addresses" endpoint.** + + The bulk verification API allows you to submit CSV files to be processed + through our address verification engine. Each file can contain up to 250,000 + addresses, and the output lines up with what is returned from our batch + verification API. + + Note that you will be invoiced for every list that processes successfully. + You can pre-purchase bulk verification credits from our + [dashboard](https://app.postgrid.com/dashboard/upgrade) to prevent this. + However, these cannot be used for geocoded lists, and you must individually + pay for every list that you process with those flags. + + **Also note that in order to access bulk geocoding you must contact** + [support@postgrid.com](mailto:support@postgrid.com) **to enable the feature.** + """ + from .resources.bulk_verification import BulkVerificationResource + + return BulkVerificationResource(self) + @cached_property def print_mail(self) -> PrintMailResource: from .resources.print_mail import PrintMailResource @@ -397,6 +422,30 @@ def intl_address_verification(self) -> AsyncIntlAddressVerificationResource: return AsyncIntlAddressVerificationResource(self) + @cached_property + def bulk_verification(self) -> AsyncBulkVerificationResource: + """ + **Note: For verifying batches of addresses in real-time via JSON, please use + the "Batch Verify Addresses" endpoint.** + + The bulk verification API allows you to submit CSV files to be processed + through our address verification engine. Each file can contain up to 250,000 + addresses, and the output lines up with what is returned from our batch + verification API. + + Note that you will be invoiced for every list that processes successfully. + You can pre-purchase bulk verification credits from our + [dashboard](https://app.postgrid.com/dashboard/upgrade) to prevent this. + However, these cannot be used for geocoded lists, and you must individually + pay for every list that you process with those flags. + + **Also note that in order to access bulk geocoding you must contact** + [support@postgrid.com](mailto:support@postgrid.com) **to enable the feature.** + """ + from .resources.bulk_verification import AsyncBulkVerificationResource + + return AsyncBulkVerificationResource(self) + @cached_property def print_mail(self) -> AsyncPrintMailResource: from .resources.print_mail import AsyncPrintMailResource @@ -584,6 +633,30 @@ def intl_address_verification(self) -> intl_address_verification.IntlAddressVeri return IntlAddressVerificationResourceWithRawResponse(self._client.intl_address_verification) + @cached_property + def bulk_verification(self) -> bulk_verification.BulkVerificationResourceWithRawResponse: + """ + **Note: For verifying batches of addresses in real-time via JSON, please use + the "Batch Verify Addresses" endpoint.** + + The bulk verification API allows you to submit CSV files to be processed + through our address verification engine. Each file can contain up to 250,000 + addresses, and the output lines up with what is returned from our batch + verification API. + + Note that you will be invoiced for every list that processes successfully. + You can pre-purchase bulk verification credits from our + [dashboard](https://app.postgrid.com/dashboard/upgrade) to prevent this. + However, these cannot be used for geocoded lists, and you must individually + pay for every list that you process with those flags. + + **Also note that in order to access bulk geocoding you must contact** + [support@postgrid.com](mailto:support@postgrid.com) **to enable the feature.** + """ + from .resources.bulk_verification import BulkVerificationResourceWithRawResponse + + return BulkVerificationResourceWithRawResponse(self._client.bulk_verification) + @cached_property def print_mail(self) -> print_mail.PrintMailResourceWithRawResponse: from .resources.print_mail import PrintMailResourceWithRawResponse @@ -623,6 +696,30 @@ def intl_address_verification( return AsyncIntlAddressVerificationResourceWithRawResponse(self._client.intl_address_verification) + @cached_property + def bulk_verification(self) -> bulk_verification.AsyncBulkVerificationResourceWithRawResponse: + """ + **Note: For verifying batches of addresses in real-time via JSON, please use + the "Batch Verify Addresses" endpoint.** + + The bulk verification API allows you to submit CSV files to be processed + through our address verification engine. Each file can contain up to 250,000 + addresses, and the output lines up with what is returned from our batch + verification API. + + Note that you will be invoiced for every list that processes successfully. + You can pre-purchase bulk verification credits from our + [dashboard](https://app.postgrid.com/dashboard/upgrade) to prevent this. + However, these cannot be used for geocoded lists, and you must individually + pay for every list that you process with those flags. + + **Also note that in order to access bulk geocoding you must contact** + [support@postgrid.com](mailto:support@postgrid.com) **to enable the feature.** + """ + from .resources.bulk_verification import AsyncBulkVerificationResourceWithRawResponse + + return AsyncBulkVerificationResourceWithRawResponse(self._client.bulk_verification) + @cached_property def print_mail(self) -> print_mail.AsyncPrintMailResourceWithRawResponse: from .resources.print_mail import AsyncPrintMailResourceWithRawResponse @@ -662,6 +759,30 @@ def intl_address_verification( return IntlAddressVerificationResourceWithStreamingResponse(self._client.intl_address_verification) + @cached_property + def bulk_verification(self) -> bulk_verification.BulkVerificationResourceWithStreamingResponse: + """ + **Note: For verifying batches of addresses in real-time via JSON, please use + the "Batch Verify Addresses" endpoint.** + + The bulk verification API allows you to submit CSV files to be processed + through our address verification engine. Each file can contain up to 250,000 + addresses, and the output lines up with what is returned from our batch + verification API. + + Note that you will be invoiced for every list that processes successfully. + You can pre-purchase bulk verification credits from our + [dashboard](https://app.postgrid.com/dashboard/upgrade) to prevent this. + However, these cannot be used for geocoded lists, and you must individually + pay for every list that you process with those flags. + + **Also note that in order to access bulk geocoding you must contact** + [support@postgrid.com](mailto:support@postgrid.com) **to enable the feature.** + """ + from .resources.bulk_verification import BulkVerificationResourceWithStreamingResponse + + return BulkVerificationResourceWithStreamingResponse(self._client.bulk_verification) + @cached_property def print_mail(self) -> print_mail.PrintMailResourceWithStreamingResponse: from .resources.print_mail import PrintMailResourceWithStreamingResponse @@ -701,6 +822,30 @@ def intl_address_verification( return AsyncIntlAddressVerificationResourceWithStreamingResponse(self._client.intl_address_verification) + @cached_property + def bulk_verification(self) -> bulk_verification.AsyncBulkVerificationResourceWithStreamingResponse: + """ + **Note: For verifying batches of addresses in real-time via JSON, please use + the "Batch Verify Addresses" endpoint.** + + The bulk verification API allows you to submit CSV files to be processed + through our address verification engine. Each file can contain up to 250,000 + addresses, and the output lines up with what is returned from our batch + verification API. + + Note that you will be invoiced for every list that processes successfully. + You can pre-purchase bulk verification credits from our + [dashboard](https://app.postgrid.com/dashboard/upgrade) to prevent this. + However, these cannot be used for geocoded lists, and you must individually + pay for every list that you process with those flags. + + **Also note that in order to access bulk geocoding you must contact** + [support@postgrid.com](mailto:support@postgrid.com) **to enable the feature.** + """ + from .resources.bulk_verification import AsyncBulkVerificationResourceWithStreamingResponse + + return AsyncBulkVerificationResourceWithStreamingResponse(self._client.bulk_verification) + @cached_property def print_mail(self) -> print_mail.AsyncPrintMailResourceWithStreamingResponse: from .resources.print_mail import AsyncPrintMailResourceWithStreamingResponse diff --git a/src/postgrid/_files.py b/src/postgrid/_files.py index 76da9e0..0ce1a1a 100644 --- a/src/postgrid/_files.py +++ b/src/postgrid/_files.py @@ -36,7 +36,7 @@ def assert_is_file_content(obj: object, *, key: str | None = None) -> None: if not is_file_content(obj): prefix = f"Expected entry at `{key}`" if key is not None else f"Expected file input `{obj!r}`" raise RuntimeError( - f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead." + f"{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/postgrid/postgrid-python/tree/main#file-uploads" ) from None diff --git a/src/postgrid/resources/__init__.py b/src/postgrid/resources/__init__.py index 2375536..37ee5c7 100644 --- a/src/postgrid/resources/__init__.py +++ b/src/postgrid/resources/__init__.py @@ -8,6 +8,14 @@ PrintMailResourceWithStreamingResponse, AsyncPrintMailResourceWithStreamingResponse, ) +from .bulk_verification import ( + BulkVerificationResource, + AsyncBulkVerificationResource, + BulkVerificationResourceWithRawResponse, + AsyncBulkVerificationResourceWithRawResponse, + BulkVerificationResourceWithStreamingResponse, + AsyncBulkVerificationResourceWithStreamingResponse, +) from .address_verification import ( AddressVerificationResource, AsyncAddressVerificationResource, @@ -38,6 +46,12 @@ "AsyncIntlAddressVerificationResourceWithRawResponse", "IntlAddressVerificationResourceWithStreamingResponse", "AsyncIntlAddressVerificationResourceWithStreamingResponse", + "BulkVerificationResource", + "AsyncBulkVerificationResource", + "BulkVerificationResourceWithRawResponse", + "AsyncBulkVerificationResourceWithRawResponse", + "BulkVerificationResourceWithStreamingResponse", + "AsyncBulkVerificationResourceWithStreamingResponse", "PrintMailResource", "AsyncPrintMailResource", "PrintMailResourceWithRawResponse", diff --git a/src/postgrid/resources/address_verification.py b/src/postgrid/resources/address_verification.py index 6e35ea1..eb5ec7d 100644 --- a/src/postgrid/resources/address_verification.py +++ b/src/postgrid/resources/address_verification.py @@ -190,11 +190,15 @@ def batch_verification( be freeform or structured, matching the same input formats accepted by the single verification endpoint. + - Accepts up to 2,000 addresses per request. - Uses 1 lookup per address (plus 1 more per address if geocoding). - Requires a secret API key. - Returns results in the same order as the input addresses. - If an individual address fails, its result will contain an `error` field rather than a `verifiedAddress`. + - If you are not subscribed and the batch would exceed your remaining free + lookups, the entire batch fails (nothing is verified). Size your batch to the + number of lookups you have left. Args: addresses: Array of addresses to verify. Each item can be a freeform string or structured @@ -312,7 +316,8 @@ def get_lookup_info( Useful for checking how many lookups you have consumed and whether you are on a paid - plan. + plan. If you are not subscribed, any lookup past your free limit will fail — use + this endpoint to check your remaining lookups. """ return self._get( "/v1/addver/", @@ -831,11 +836,15 @@ async def batch_verification( be freeform or structured, matching the same input formats accepted by the single verification endpoint. + - Accepts up to 2,000 addresses per request. - Uses 1 lookup per address (plus 1 more per address if geocoding). - Requires a secret API key. - Returns results in the same order as the input addresses. - If an individual address fails, its result will contain an `error` field rather than a `verifiedAddress`. + - If you are not subscribed and the batch would exceed your remaining free + lookups, the entire batch fails (nothing is verified). Size your batch to the + number of lookups you have left. Args: addresses: Array of addresses to verify. Each item can be a freeform string or structured @@ -953,7 +962,8 @@ async def get_lookup_info( Useful for checking how many lookups you have consumed and whether you are on a paid - plan. + plan. If you are not subscribed, any lookup past your free limit will fail — use + this endpoint to check your remaining lookups. """ return await self._get( "/v1/addver/", diff --git a/src/postgrid/resources/bulk_verification.py b/src/postgrid/resources/bulk_verification.py new file mode 100644 index 0000000..8996614 --- /dev/null +++ b/src/postgrid/resources/bulk_verification.py @@ -0,0 +1,494 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Mapping, cast + +import httpx + +from ..types import bulk_verification_list_params, bulk_verification_upload_params +from .._files import deepcopy_with_paths +from .._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given +from .._utils import extract_files, path_template, maybe_transform, async_maybe_transform +from .._compat import cached_property +from .._resource import SyncAPIResource, AsyncAPIResource +from .._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from .._base_client import make_request_options +from ..types.bulk_verification_list_response import BulkVerificationListResponse +from ..types.bulk_verification_upload_response import BulkVerificationUploadResponse +from ..types.bulk_verification_retrieve_response import BulkVerificationRetrieveResponse + +__all__ = ["BulkVerificationResource", "AsyncBulkVerificationResource"] + + +class BulkVerificationResource(SyncAPIResource): + """ + **Note: For verifying batches of addresses in real-time via JSON, please use + the "Batch Verify Addresses" endpoint.** + + The bulk verification API allows you to submit CSV files to be processed + through our address verification engine. Each file can contain up to 250,000 + addresses, and the output lines up with what is returned from our batch + verification API. + + Note that you will be invoiced for every list that processes successfully. + You can pre-purchase bulk verification credits from our + [dashboard](https://app.postgrid.com/dashboard/upgrade) to prevent this. + However, these cannot be used for geocoded lists, and you must individually + pay for every list that you process with those flags. + + **Also note that in order to access bulk geocoding you must contact** + [support@postgrid.com](mailto:support@postgrid.com) **to enable the feature.** + """ + + @cached_property + def with_raw_response(self) -> BulkVerificationResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/postgrid/postgrid-python#accessing-raw-response-data-eg-headers + """ + return BulkVerificationResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> BulkVerificationResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/postgrid/postgrid-python#with_streaming_response + """ + return BulkVerificationResourceWithStreamingResponse(self) + + def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> BulkVerificationRetrieveResponse: + """ + Retrieve a single bulk verification list by ID, including its processing status + and — once processed — a link to the output CSV. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get( + path_template("/v1/addver_lists/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkVerificationRetrieveResponse, + ) + + def list( + self, + *, + limit: int | Omit = omit, + skip: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> BulkVerificationListResponse: + """ + Retrieve a list of your bulk verification lists. + + Args: + limit: The maximum number of lists to return. + + skip: The number of lists to skip past, for pagination. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get( + "/v1/addver_lists", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "skip": skip, + }, + bulk_verification_list_params.BulkVerificationListParams, + ), + ), + cast_to=BulkVerificationListResponse, + ) + + def upload( + self, + *, + file: FileTypes, + mappings: bulk_verification_upload_params.Mappings, + name: str, + default_country: str | Omit = omit, + run_ccoa: bool | Omit = omit, + run_ncoa: bool | Omit = omit, + use_geocode: bool | Omit = omit, + use_intl_verification: bool | Omit = omit, + use_proper_case: bool | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> BulkVerificationUploadResponse: + """Upload a CSV file of addresses to be verified in bulk. + + Supply a `mappings` + object describing which CSV columns correspond to which address fields. + + Args: + mappings: The mapping of your CSV column names to PostGrid address fields. Each value is + the name of a column in your uploaded file. + + name: A name for the uploaded list. This only affects what is displayed in the + dashboard. + + default_country: An ISO 2-letter country code used as the fallback when a row is missing a value + in the `country` column. + + run_ccoa: Whether to run CCOA (Canada Post change of address) on the list. Note that a + list cannot run both NCOA and CCOA — split mixed US/Canadian files into separate + lists. + + run_ncoa: Whether to run NCOA (US National Change of Address) on the list. + + use_geocode: Whether to append geographical location information (latitude, longitude) to + your output. Bulk geocoding must be enabled by contacting support. + + use_intl_verification: Whether to perform international (outside US & Canada) verification. + + use_proper_case: Whether to return addresses in Proper Case. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + body = deepcopy_with_paths( + { + "file": file, + "mappings": mappings, + "name": name, + "default_country": default_country, + "run_ccoa": run_ccoa, + "run_ncoa": run_ncoa, + "use_geocode": use_geocode, + "use_intl_verification": use_intl_verification, + "use_proper_case": use_proper_case, + }, + [["file"]], + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return self._post( + "/v1/addver_lists", + body=maybe_transform(body, bulk_verification_upload_params.BulkVerificationUploadParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkVerificationUploadResponse, + ) + + +class AsyncBulkVerificationResource(AsyncAPIResource): + """ + **Note: For verifying batches of addresses in real-time via JSON, please use + the "Batch Verify Addresses" endpoint.** + + The bulk verification API allows you to submit CSV files to be processed + through our address verification engine. Each file can contain up to 250,000 + addresses, and the output lines up with what is returned from our batch + verification API. + + Note that you will be invoiced for every list that processes successfully. + You can pre-purchase bulk verification credits from our + [dashboard](https://app.postgrid.com/dashboard/upgrade) to prevent this. + However, these cannot be used for geocoded lists, and you must individually + pay for every list that you process with those flags. + + **Also note that in order to access bulk geocoding you must contact** + [support@postgrid.com](mailto:support@postgrid.com) **to enable the feature.** + """ + + @cached_property + def with_raw_response(self) -> AsyncBulkVerificationResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/postgrid/postgrid-python#accessing-raw-response-data-eg-headers + """ + return AsyncBulkVerificationResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncBulkVerificationResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/postgrid/postgrid-python#with_streaming_response + """ + return AsyncBulkVerificationResourceWithStreamingResponse(self) + + async def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> BulkVerificationRetrieveResponse: + """ + Retrieve a single bulk verification list by ID, including its processing status + and — once processed — a link to the output CSV. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._get( + path_template("/v1/addver_lists/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkVerificationRetrieveResponse, + ) + + async def list( + self, + *, + limit: int | Omit = omit, + skip: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> BulkVerificationListResponse: + """ + Retrieve a list of your bulk verification lists. + + Args: + limit: The maximum number of lists to return. + + skip: The number of lists to skip past, for pagination. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return await self._get( + "/v1/addver_lists", + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform( + { + "limit": limit, + "skip": skip, + }, + bulk_verification_list_params.BulkVerificationListParams, + ), + ), + cast_to=BulkVerificationListResponse, + ) + + async def upload( + self, + *, + file: FileTypes, + mappings: bulk_verification_upload_params.Mappings, + name: str, + default_country: str | Omit = omit, + run_ccoa: bool | Omit = omit, + run_ncoa: bool | Omit = omit, + use_geocode: bool | Omit = omit, + use_intl_verification: bool | Omit = omit, + use_proper_case: bool | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> BulkVerificationUploadResponse: + """Upload a CSV file of addresses to be verified in bulk. + + Supply a `mappings` + object describing which CSV columns correspond to which address fields. + + Args: + mappings: The mapping of your CSV column names to PostGrid address fields. Each value is + the name of a column in your uploaded file. + + name: A name for the uploaded list. This only affects what is displayed in the + dashboard. + + default_country: An ISO 2-letter country code used as the fallback when a row is missing a value + in the `country` column. + + run_ccoa: Whether to run CCOA (Canada Post change of address) on the list. Note that a + list cannot run both NCOA and CCOA — split mixed US/Canadian files into separate + lists. + + run_ncoa: Whether to run NCOA (US National Change of Address) on the list. + + use_geocode: Whether to append geographical location information (latitude, longitude) to + your output. Bulk geocoding must be enabled by contacting support. + + use_intl_verification: Whether to perform international (outside US & Canada) verification. + + use_proper_case: Whether to return addresses in Proper Case. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + body = deepcopy_with_paths( + { + "file": file, + "mappings": mappings, + "name": name, + "default_country": default_country, + "run_ccoa": run_ccoa, + "run_ncoa": run_ncoa, + "use_geocode": use_geocode, + "use_intl_verification": use_intl_verification, + "use_proper_case": use_proper_case, + }, + [["file"]], + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["file"]]) + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return await self._post( + "/v1/addver_lists", + body=await async_maybe_transform(body, bulk_verification_upload_params.BulkVerificationUploadParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=BulkVerificationUploadResponse, + ) + + +class BulkVerificationResourceWithRawResponse: + def __init__(self, bulk_verification: BulkVerificationResource) -> None: + self._bulk_verification = bulk_verification + + self.retrieve = to_raw_response_wrapper( + bulk_verification.retrieve, + ) + self.list = to_raw_response_wrapper( + bulk_verification.list, + ) + self.upload = to_raw_response_wrapper( + bulk_verification.upload, + ) + + +class AsyncBulkVerificationResourceWithRawResponse: + def __init__(self, bulk_verification: AsyncBulkVerificationResource) -> None: + self._bulk_verification = bulk_verification + + self.retrieve = async_to_raw_response_wrapper( + bulk_verification.retrieve, + ) + self.list = async_to_raw_response_wrapper( + bulk_verification.list, + ) + self.upload = async_to_raw_response_wrapper( + bulk_verification.upload, + ) + + +class BulkVerificationResourceWithStreamingResponse: + def __init__(self, bulk_verification: BulkVerificationResource) -> None: + self._bulk_verification = bulk_verification + + self.retrieve = to_streamed_response_wrapper( + bulk_verification.retrieve, + ) + self.list = to_streamed_response_wrapper( + bulk_verification.list, + ) + self.upload = to_streamed_response_wrapper( + bulk_verification.upload, + ) + + +class AsyncBulkVerificationResourceWithStreamingResponse: + def __init__(self, bulk_verification: AsyncBulkVerificationResource) -> None: + self._bulk_verification = bulk_verification + + self.retrieve = async_to_streamed_response_wrapper( + bulk_verification.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + bulk_verification.list, + ) + self.upload = async_to_streamed_response_wrapper( + bulk_verification.upload, + ) diff --git a/src/postgrid/resources/intl_address_verification.py b/src/postgrid/resources/intl_address_verification.py index 2777590..200c01a 100644 --- a/src/postgrid/resources/intl_address_verification.py +++ b/src/postgrid/resources/intl_address_verification.py @@ -144,11 +144,15 @@ def batch_verification( be freeform or structured, matching the same input formats accepted by the single verification endpoint. + - Accepts up to 2,000 addresses per request. - Uses 1 lookup per address. - Requires a secret API key. - Returns results in the same order as the input addresses. - If an individual address fails, its result will contain an `error` field rather than a `verifiedAddress`. + - If you are not subscribed and the batch would exceed your remaining free + lookups, the entire batch fails (nothing is verified). Size your batch to the + number of lookups you have left. Args: addresses: Array of addresses to verify. Each item can be a freeform string or a structured @@ -213,16 +217,19 @@ def get_autocomplete_advanced_previews( populating an autocomplete dropdown. **Regular mode** — supply `partialStreet` to search by partial street address. - Results may include `Address` types (resolvable directly) and `Container` types - (buildings/complexes that require a follow-up call). + Results may include directly-resolvable `Address` results and non-`Address` + results (e.g. `BuildingNumber`) that represent buildings/complexes requiring a + follow-up call. - **Advanced mode** — supply `advanced=true` and a `container` ID (from a previous - regular call) to drill into a building or complex and retrieve individual unit - addresses. + **Advanced mode** — supply `advanced=true` and a `container` ID (the `id` of a + non-`Address` result from a previous regular call) to drill into a building or + complex and retrieve individual unit addresses. Results with `type: "Address"` can be fully resolved by passing their `id` to `POST /completions`. + - Results are biased by the caller's IP address by default; pass + `disableIPBiasing=true` to turn this off. - Does not consume a lookup. Args: @@ -289,16 +296,19 @@ def get_autocomplete_previews( populating an autocomplete dropdown. **Regular mode** — supply `partialStreet` to search by partial street address. - Results may include `Address` types (resolvable directly) and `Container` types - (buildings/complexes that require a follow-up call). + Results may include directly-resolvable `Address` results and non-`Address` + results (e.g. `BuildingNumber`) that represent buildings/complexes requiring a + follow-up call. - **Advanced mode** — supply `advanced=true` and a `container` ID (from a previous - regular call) to drill into a building or complex and retrieve individual unit - addresses. + **Advanced mode** — supply `advanced=true` and a `container` ID (the `id` of a + non-`Address` result from a previous regular call) to drill into a building or + complex and retrieve individual unit addresses. Results with `type: "Address"` can be fully resolved by passing their `id` to `POST /completions`. + - Results are biased by the caller's IP address by default; pass + `disableIPBiasing=true` to turn this off. - Does not consume a lookup. Args: @@ -550,11 +560,15 @@ async def batch_verification( be freeform or structured, matching the same input formats accepted by the single verification endpoint. + - Accepts up to 2,000 addresses per request. - Uses 1 lookup per address. - Requires a secret API key. - Returns results in the same order as the input addresses. - If an individual address fails, its result will contain an `error` field rather than a `verifiedAddress`. + - If you are not subscribed and the batch would exceed your remaining free + lookups, the entire batch fails (nothing is verified). Size your batch to the + number of lookups you have left. Args: addresses: Array of addresses to verify. Each item can be a freeform string or a structured @@ -619,16 +633,19 @@ async def get_autocomplete_advanced_previews( populating an autocomplete dropdown. **Regular mode** — supply `partialStreet` to search by partial street address. - Results may include `Address` types (resolvable directly) and `Container` types - (buildings/complexes that require a follow-up call). + Results may include directly-resolvable `Address` results and non-`Address` + results (e.g. `BuildingNumber`) that represent buildings/complexes requiring a + follow-up call. - **Advanced mode** — supply `advanced=true` and a `container` ID (from a previous - regular call) to drill into a building or complex and retrieve individual unit - addresses. + **Advanced mode** — supply `advanced=true` and a `container` ID (the `id` of a + non-`Address` result from a previous regular call) to drill into a building or + complex and retrieve individual unit addresses. Results with `type: "Address"` can be fully resolved by passing their `id` to `POST /completions`. + - Results are biased by the caller's IP address by default; pass + `disableIPBiasing=true` to turn this off. - Does not consume a lookup. Args: @@ -695,16 +712,19 @@ async def get_autocomplete_previews( populating an autocomplete dropdown. **Regular mode** — supply `partialStreet` to search by partial street address. - Results may include `Address` types (resolvable directly) and `Container` types - (buildings/complexes that require a follow-up call). + Results may include directly-resolvable `Address` results and non-`Address` + results (e.g. `BuildingNumber`) that represent buildings/complexes requiring a + follow-up call. - **Advanced mode** — supply `advanced=true` and a `container` ID (from a previous - regular call) to drill into a building or complex and retrieve individual unit - addresses. + **Advanced mode** — supply `advanced=true` and a `container` ID (the `id` of a + non-`Address` result from a previous regular call) to drill into a building or + complex and retrieve individual unit addresses. Results with `type: "Address"` can be fully resolved by passing their `id` to `POST /completions`. + - Results are biased by the caller's IP address by default; pass + `disableIPBiasing=true` to turn this off. - Does not consume a lookup. Args: diff --git a/src/postgrid/resources/print_mail/__init__.py b/src/postgrid/resources/print_mail/__init__.py index 610d7b6..dadd54e 100644 --- a/src/postgrid/resources/print_mail/__init__.py +++ b/src/postgrid/resources/print_mail/__init__.py @@ -128,6 +128,14 @@ MailingListsResourceWithStreamingResponse, AsyncMailingListsResourceWithStreamingResponse, ) +from .return_envelopes import ( + ReturnEnvelopesResource, + AsyncReturnEnvelopesResource, + ReturnEnvelopesResourceWithRawResponse, + AsyncReturnEnvelopesResourceWithRawResponse, + ReturnEnvelopesResourceWithStreamingResponse, + AsyncReturnEnvelopesResourceWithStreamingResponse, +) from .sub_organizations import ( SubOrganizationsResource, AsyncSubOrganizationsResource, @@ -230,6 +238,12 @@ "AsyncSelfMailersResourceWithRawResponse", "SelfMailersResourceWithStreamingResponse", "AsyncSelfMailersResourceWithStreamingResponse", + "ReturnEnvelopesResource", + "AsyncReturnEnvelopesResource", + "ReturnEnvelopesResourceWithRawResponse", + "AsyncReturnEnvelopesResourceWithRawResponse", + "ReturnEnvelopesResourceWithStreamingResponse", + "AsyncReturnEnvelopesResourceWithStreamingResponse", "CampaignsResource", "AsyncCampaignsResource", "CampaignsResourceWithRawResponse", diff --git a/src/postgrid/resources/print_mail/bank_accounts.py b/src/postgrid/resources/print_mail/bank_accounts.py index 9cb4d8a..f2e1b68 100644 --- a/src/postgrid/resources/print_mail/bank_accounts.py +++ b/src/postgrid/resources/print_mail/bank_accounts.py @@ -28,6 +28,8 @@ class BankAccountsResource(SyncAPIResource): + """Manage bank accounts that will be used for mailing cheques.""" + @cached_property def with_raw_response(self) -> BankAccountsResourceWithRawResponse: """ @@ -80,6 +82,10 @@ def create( You must specify _either_ `signatureImage` or `signatureText`. The image can be supplied as either a URL or a multipart file upload. + Note that the reasonable character limit for `signatureText` is 6 capital + letters or 20 lowercase letters — anything exceeding that will likely overflow + onto a new line. + Args: account_number: The account number of the bank account. @@ -150,6 +156,10 @@ def create( You must specify _either_ `signatureImage` or `signatureText`. The image can be supplied as either a URL or a multipart file upload. + Note that the reasonable character limit for `signatureText` is 6 capital + letters or 20 lowercase letters — anything exceeding that will likely overflow + onto a new line. + Args: account_number: The account number of the bank account. @@ -221,6 +231,10 @@ def create( You must specify _either_ `signatureImage` or `signatureText`. The image can be supplied as either a URL or a multipart file upload. + Note that the reasonable character limit for `signatureText` is 6 capital + letters or 20 lowercase letters — anything exceeding that will likely overflow + onto a new line. + Args: account_number: The account number of the bank account. @@ -326,6 +340,9 @@ def retrieve( """ Retrieve a bank account by ID. + Note that we do not return the complete account number or the signature image + for security reasons. + Args: extra_headers: Send extra headers @@ -361,6 +378,9 @@ def list( """ Get a list of bank accounts. + Note that we do not return the complete account number or the signature image + for security reasons. + Args: search: You can supply any string to help narrow down the list of resources. For example, if you pass `"New York"` (quoted), it will return resources that have @@ -432,6 +452,8 @@ def delete( class AsyncBankAccountsResource(AsyncAPIResource): + """Manage bank accounts that will be used for mailing cheques.""" + @cached_property def with_raw_response(self) -> AsyncBankAccountsResourceWithRawResponse: """ @@ -484,6 +506,10 @@ async def create( You must specify _either_ `signatureImage` or `signatureText`. The image can be supplied as either a URL or a multipart file upload. + Note that the reasonable character limit for `signatureText` is 6 capital + letters or 20 lowercase letters — anything exceeding that will likely overflow + onto a new line. + Args: account_number: The account number of the bank account. @@ -554,6 +580,10 @@ async def create( You must specify _either_ `signatureImage` or `signatureText`. The image can be supplied as either a URL or a multipart file upload. + Note that the reasonable character limit for `signatureText` is 6 capital + letters or 20 lowercase letters — anything exceeding that will likely overflow + onto a new line. + Args: account_number: The account number of the bank account. @@ -625,6 +655,10 @@ async def create( You must specify _either_ `signatureImage` or `signatureText`. The image can be supplied as either a URL or a multipart file upload. + Note that the reasonable character limit for `signatureText` is 6 capital + letters or 20 lowercase letters — anything exceeding that will likely overflow + onto a new line. + Args: account_number: The account number of the bank account. @@ -730,6 +764,9 @@ async def retrieve( """ Retrieve a bank account by ID. + Note that we do not return the complete account number or the signature image + for security reasons. + Args: extra_headers: Send extra headers @@ -765,6 +802,9 @@ def list( """ Get a list of bank accounts. + Note that we do not return the complete account number or the signature image + for security reasons. + Args: search: You can supply any string to help narrow down the list of resources. For example, if you pass `"New York"` (quoted), it will return resources that have diff --git a/src/postgrid/resources/print_mail/boxes.py b/src/postgrid/resources/print_mail/boxes.py index bfb8ea2..dc64b23 100644 --- a/src/postgrid/resources/print_mail/boxes.py +++ b/src/postgrid/resources/print_mail/boxes.py @@ -31,6 +31,8 @@ class BoxesResource(SyncAPIResource): + """Create and manage box orders.""" + @cached_property def with_raw_response(self) -> BoxesResourceWithRawResponse: """ @@ -330,6 +332,8 @@ def progressions( class AsyncBoxesResource(AsyncAPIResource): + """Create and manage box orders.""" + @cached_property def with_raw_response(self) -> AsyncBoxesResourceWithRawResponse: """ diff --git a/src/postgrid/resources/print_mail/cheques.py b/src/postgrid/resources/print_mail/cheques.py index 2a25344..adf639b 100644 --- a/src/postgrid/resources/print_mail/cheques.py +++ b/src/postgrid/resources/print_mail/cheques.py @@ -8,7 +8,7 @@ import httpx -from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ..._types import Body, Omit, Query, Headers, NotGiven, Base64FileInput, omit, not_given from ..._utils import path_template, maybe_transform, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource @@ -30,6 +30,8 @@ class ChequesResource(SyncAPIResource): + """Create and manage cheque orders.""" + @cached_property def with_raw_response(self) -> ChequesResourceWithRawResponse: """ @@ -60,7 +62,11 @@ def create( description: str | Omit = omit, digital_only: DigitalOnlyParam | Omit = omit, envelope: Union[Literal["standard"], str] | Omit = omit, - logo_url: str | Omit = omit, + letter_html: str | Omit = omit, + letter_pdf: Union[str, Base64FileInput] | Omit = omit, + letter_settings: cheque_create_params.LetterSettings | Omit = omit, + letter_template: str | Omit = omit, + logo: str | Omit = omit, mailing_class: Literal[ "first_class", "standard_class", @@ -96,6 +102,7 @@ def create( metadata: Dict[str, object] | Omit = omit, number: int | Omit = omit, redirect_to: cheque_create_params.RedirectTo | Omit = omit, + return_envelope: str | Omit = omit, send_date: Union[str, datetime] | Omit = omit, size: ChequeSize | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -112,7 +119,9 @@ def create( If you would like to create a digitalOnly cheque, the digitalOnly object with the watermark will need to be passed in. Feature is available on request, e-mail - support@postgrid.com for access. + support@postgrid.com for access. Digital-only cheques are not sent out — they + are created with a `cancelled` status and a cancellation reason of + `digital_only`. Example request body: @@ -157,7 +166,18 @@ def create( envelope: The envelope of the cheque. If a custom envelope ID is not specified, defaults to `standard`. - logo_url: An optional logo URL for the cheque. This will be placed next to the recipient + letter_html: The raw HTML content for a letter attached to the cheque, if any. You can supply + _either_ this, `letterTemplate`, or `letterPDF`, but not more than one. + + letter_pdf: A URL pointing to a PDF for the letter attached to the cheque, or the PDF file + itself when uploaded via a multipart form request. You can supply _either_ this, + `letterHTML`, or `letterTemplate`, but not more than one. + + letter_settings: Settings for a letter attached to a cheque. + + letter_template: A Template ID for the letter attached to the cheque, if any. + + logo: An optional logo URL for the cheque. This will be placed next to the recipient address at the top left corner of the cheque. This needs to be a public link to an image file (e.g. a PNG or JPEG file). @@ -185,6 +205,9 @@ def create( mail it forward to the final recipient yourself. One use case for this is signing cheques at your office before mailing them out yourself. + return_envelope: The return envelope (ID) sent out with the cheque, if any. Note that you must + first order return envelopes using the Return Envelopes API. + send_date: This order will transition from `ready` to `printing` on the day after this date. You can use this parameter to schedule orders for a future date. @@ -210,7 +233,11 @@ def create( "description": description, "digital_only": digital_only, "envelope": envelope, - "logo_url": logo_url, + "letter_html": letter_html, + "letter_pdf": letter_pdf, + "letter_settings": letter_settings, + "letter_template": letter_template, + "logo": logo, "mailing_class": mailing_class, "memo": memo, "merge_variables": merge_variables, @@ -218,6 +245,7 @@ def create( "metadata": metadata, "number": number, "redirect_to": redirect_to, + "return_envelope": return_envelope, "send_date": send_date, "size": size, }, @@ -500,6 +528,8 @@ def retrieve_with_deposit_ready_pdf( class AsyncChequesResource(AsyncAPIResource): + """Create and manage cheque orders.""" + @cached_property def with_raw_response(self) -> AsyncChequesResourceWithRawResponse: """ @@ -530,7 +560,11 @@ async def create( description: str | Omit = omit, digital_only: DigitalOnlyParam | Omit = omit, envelope: Union[Literal["standard"], str] | Omit = omit, - logo_url: str | Omit = omit, + letter_html: str | Omit = omit, + letter_pdf: Union[str, Base64FileInput] | Omit = omit, + letter_settings: cheque_create_params.LetterSettings | Omit = omit, + letter_template: str | Omit = omit, + logo: str | Omit = omit, mailing_class: Literal[ "first_class", "standard_class", @@ -566,6 +600,7 @@ async def create( metadata: Dict[str, object] | Omit = omit, number: int | Omit = omit, redirect_to: cheque_create_params.RedirectTo | Omit = omit, + return_envelope: str | Omit = omit, send_date: Union[str, datetime] | Omit = omit, size: ChequeSize | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. @@ -582,7 +617,9 @@ async def create( If you would like to create a digitalOnly cheque, the digitalOnly object with the watermark will need to be passed in. Feature is available on request, e-mail - support@postgrid.com for access. + support@postgrid.com for access. Digital-only cheques are not sent out — they + are created with a `cancelled` status and a cancellation reason of + `digital_only`. Example request body: @@ -627,7 +664,18 @@ async def create( envelope: The envelope of the cheque. If a custom envelope ID is not specified, defaults to `standard`. - logo_url: An optional logo URL for the cheque. This will be placed next to the recipient + letter_html: The raw HTML content for a letter attached to the cheque, if any. You can supply + _either_ this, `letterTemplate`, or `letterPDF`, but not more than one. + + letter_pdf: A URL pointing to a PDF for the letter attached to the cheque, or the PDF file + itself when uploaded via a multipart form request. You can supply _either_ this, + `letterHTML`, or `letterTemplate`, but not more than one. + + letter_settings: Settings for a letter attached to a cheque. + + letter_template: A Template ID for the letter attached to the cheque, if any. + + logo: An optional logo URL for the cheque. This will be placed next to the recipient address at the top left corner of the cheque. This needs to be a public link to an image file (e.g. a PNG or JPEG file). @@ -655,6 +703,9 @@ async def create( mail it forward to the final recipient yourself. One use case for this is signing cheques at your office before mailing them out yourself. + return_envelope: The return envelope (ID) sent out with the cheque, if any. Note that you must + first order return envelopes using the Return Envelopes API. + send_date: This order will transition from `ready` to `printing` on the day after this date. You can use this parameter to schedule orders for a future date. @@ -680,7 +731,11 @@ async def create( "description": description, "digital_only": digital_only, "envelope": envelope, - "logo_url": logo_url, + "letter_html": letter_html, + "letter_pdf": letter_pdf, + "letter_settings": letter_settings, + "letter_template": letter_template, + "logo": logo, "mailing_class": mailing_class, "memo": memo, "merge_variables": merge_variables, @@ -688,6 +743,7 @@ async def create( "metadata": metadata, "number": number, "redirect_to": redirect_to, + "return_envelope": return_envelope, "send_date": send_date, "size": size, }, diff --git a/src/postgrid/resources/print_mail/contacts.py b/src/postgrid/resources/print_mail/contacts.py index 3270815..bec762c 100644 --- a/src/postgrid/resources/print_mail/contacts.py +++ b/src/postgrid/resources/print_mail/contacts.py @@ -27,6 +27,26 @@ class ContactsResource(SyncAPIResource): + """Manage contacts that you can mail to. + + Test mode addresses will always have a + `verified` status. In live mode, they may be `verified`, `corrected`, or + `failed`. Addresses that fail to be corrected are likely undeliverable, but + you can still send to them if you want to. + + For test mode contacts, you have the ability to assert the `addressStatus` of + the contact by passing specific values to the `description` field. To receive + an `addressStatus` of `failed`, the description of the contact should be a + string with the exact value `test failed`. For an `addressStatus` value of + `corrected`, the description of the contact should be a string with the exact + value `test corrected`. + + Our address correction engine will often be able to fix missing postal/ZIP + codes, city names, and also append ZIP+4. It is SERP (Canada Post) and CASS + (USPS) certified, so you can rest assured that if an address is verified, we + can deliver to it. + """ + @cached_property def with_raw_response(self) -> ContactsResourceWithRawResponse: """ @@ -65,6 +85,7 @@ def create( phone_number: str | Omit = omit, postal_or_zip: str | Omit = omit, province_or_state: str | Omit = omit, + secret: bool | Omit = omit, skip_verification: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -120,6 +141,10 @@ def create( province_or_state: Province or state of the contact's address. + secret: If `true`, the contact's details are hidden from the dashboard and API responses + apart from the final print. The contact ID can then be used as a token for + sending mail without giving access to the underlying data. + skip_verification: If `true`, PostGrid will skip running this contact's address through our address verification system. @@ -152,6 +177,7 @@ def create( phone_number: str | Omit = omit, postal_or_zip: str | Omit = omit, province_or_state: str | Omit = omit, + secret: bool | Omit = omit, skip_verification: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -207,6 +233,10 @@ def create( province_or_state: Province or state of the contact's address. + secret: If `true`, the contact's details are hidden from the dashboard and API responses + apart from the final print. The contact ID can then be used as a token for + sending mail without giving access to the underlying data. + skip_verification: If `true`, PostGrid will skip running this contact's address through our address verification system. @@ -239,6 +269,7 @@ def create( phone_number: str | Omit = omit, postal_or_zip: str | Omit = omit, province_or_state: str | Omit = omit, + secret: bool | Omit = omit, skip_verification: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -266,6 +297,7 @@ def create( "phone_number": phone_number, "postal_or_zip": postal_or_zip, "province_or_state": province_or_state, + "secret": secret, "skip_verification": skip_verification, }, contact_create_params.ContactCreateParams, @@ -397,6 +429,26 @@ def delete( class AsyncContactsResource(AsyncAPIResource): + """Manage contacts that you can mail to. + + Test mode addresses will always have a + `verified` status. In live mode, they may be `verified`, `corrected`, or + `failed`. Addresses that fail to be corrected are likely undeliverable, but + you can still send to them if you want to. + + For test mode contacts, you have the ability to assert the `addressStatus` of + the contact by passing specific values to the `description` field. To receive + an `addressStatus` of `failed`, the description of the contact should be a + string with the exact value `test failed`. For an `addressStatus` value of + `corrected`, the description of the contact should be a string with the exact + value `test corrected`. + + Our address correction engine will often be able to fix missing postal/ZIP + codes, city names, and also append ZIP+4. It is SERP (Canada Post) and CASS + (USPS) certified, so you can rest assured that if an address is verified, we + can deliver to it. + """ + @cached_property def with_raw_response(self) -> AsyncContactsResourceWithRawResponse: """ @@ -435,6 +487,7 @@ async def create( phone_number: str | Omit = omit, postal_or_zip: str | Omit = omit, province_or_state: str | Omit = omit, + secret: bool | Omit = omit, skip_verification: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -490,6 +543,10 @@ async def create( province_or_state: Province or state of the contact's address. + secret: If `true`, the contact's details are hidden from the dashboard and API responses + apart from the final print. The contact ID can then be used as a token for + sending mail without giving access to the underlying data. + skip_verification: If `true`, PostGrid will skip running this contact's address through our address verification system. @@ -522,6 +579,7 @@ async def create( phone_number: str | Omit = omit, postal_or_zip: str | Omit = omit, province_or_state: str | Omit = omit, + secret: bool | Omit = omit, skip_verification: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -577,6 +635,10 @@ async def create( province_or_state: Province or state of the contact's address. + secret: If `true`, the contact's details are hidden from the dashboard and API responses + apart from the final print. The contact ID can then be used as a token for + sending mail without giving access to the underlying data. + skip_verification: If `true`, PostGrid will skip running this contact's address through our address verification system. @@ -609,6 +671,7 @@ async def create( phone_number: str | Omit = omit, postal_or_zip: str | Omit = omit, province_or_state: str | Omit = omit, + secret: bool | Omit = omit, skip_verification: bool | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -636,6 +699,7 @@ async def create( "phone_number": phone_number, "postal_or_zip": postal_or_zip, "province_or_state": province_or_state, + "secret": secret, "skip_verification": skip_verification, }, contact_create_params.ContactCreateParams, diff --git a/src/postgrid/resources/print_mail/letters.py b/src/postgrid/resources/print_mail/letters.py index c0dea77..a680590 100644 --- a/src/postgrid/resources/print_mail/letters.py +++ b/src/postgrid/resources/print_mail/letters.py @@ -38,6 +38,8 @@ class LettersResource(SyncAPIResource): + """Create and manage letter orders.""" + @cached_property def with_raw_response(self) -> LettersResourceWithRawResponse: """ @@ -807,6 +809,8 @@ def retrieve_url( class AsyncLettersResource(AsyncAPIResource): + """Create and manage letter orders.""" + @cached_property def with_raw_response(self) -> AsyncLettersResourceWithRawResponse: """ diff --git a/src/postgrid/resources/print_mail/postcards.py b/src/postgrid/resources/print_mail/postcards.py index f95db85..aef077e 100644 --- a/src/postgrid/resources/print_mail/postcards.py +++ b/src/postgrid/resources/print_mail/postcards.py @@ -28,6 +28,8 @@ class PostcardsResource(SyncAPIResource): + """Create and manage postcard mailings.""" + @cached_property def with_raw_response(self) -> PostcardsResourceWithRawResponse: """ @@ -886,6 +888,8 @@ def retrieve_url( class AsyncPostcardsResource(AsyncAPIResource): + """Create and manage postcard mailings.""" + @cached_property def with_raw_response(self) -> AsyncPostcardsResourceWithRawResponse: """ diff --git a/src/postgrid/resources/print_mail/print_mail.py b/src/postgrid/resources/print_mail/print_mail.py index d1b68bb..8ea24b0 100644 --- a/src/postgrid/resources/print_mail/print_mail.py +++ b/src/postgrid/resources/print_mail/print_mail.py @@ -148,6 +148,14 @@ TemplateEditorSessionsResourceWithStreamingResponse, AsyncTemplateEditorSessionsResourceWithStreamingResponse, ) +from .return_envelopes.return_envelopes import ( + ReturnEnvelopesResource, + AsyncReturnEnvelopesResource, + ReturnEnvelopesResourceWithRawResponse, + AsyncReturnEnvelopesResourceWithRawResponse, + ReturnEnvelopesResourceWithStreamingResponse, + AsyncReturnEnvelopesResourceWithStreamingResponse, +) from .virtual_mailboxes.virtual_mailboxes import ( VirtualMailboxesResource, AsyncVirtualMailboxesResource, @@ -171,10 +179,35 @@ class PrintMailResource(SyncAPIResource): @cached_property def contacts(self) -> ContactsResource: + """Manage contacts that you can mail to. + + Test mode addresses will always have a + `verified` status. In live mode, they may be `verified`, `corrected`, or + `failed`. Addresses that fail to be corrected are likely undeliverable, but + you can still send to them if you want to. + + For test mode contacts, you have the ability to assert the `addressStatus` of + the contact by passing specific values to the `description` field. To receive + an `addressStatus` of `failed`, the description of the contact should be a + string with the exact value `test failed`. For an `addressStatus` value of + `corrected`, the description of the contact should be a string with the exact + value `test corrected`. + + Our address correction engine will often be able to fix missing postal/ZIP + codes, city names, and also append ZIP+4. It is SERP (Canada Post) and CASS + (USPS) certified, so you can rest assured that if an address is verified, we + can deliver to it. + """ return ContactsResource(self._client) @cached_property def templates(self) -> TemplatesResource: + """Create and manage reusable HTML templates. + + A template's HTML can include + merge variables (e.g. `{{firstName}}`) and be referenced by ID when creating + letters, postcards, cheques, and self mailers. + """ return TemplatesResource(self._client) @cached_property @@ -232,24 +265,43 @@ def events(self) -> EventsResource: @cached_property def letters(self) -> LettersResource: + """Create and manage letter orders.""" return LettersResource(self._client) @cached_property def postcards(self) -> PostcardsResource: + """Create and manage postcard mailings.""" return PostcardsResource(self._client) @cached_property def bank_accounts(self) -> BankAccountsResource: + """Manage bank accounts that will be used for mailing cheques.""" return BankAccountsResource(self._client) @cached_property def cheques(self) -> ChequesResource: + """Create and manage cheque orders.""" return ChequesResource(self._client) @cached_property def self_mailers(self) -> SelfMailersResource: + """Create and manage self mailers.""" return SelfMailersResource(self._client) + @cached_property + def return_envelopes(self) -> ReturnEnvelopesResource: + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + return ReturnEnvelopesResource(self._client) + @cached_property def campaigns(self) -> CampaignsResource: """ @@ -303,6 +355,7 @@ def sub_organizations(self) -> SubOrganizationsResource: @cached_property def boxes(self) -> BoxesResource: + """Create and manage box orders.""" return BoxesResource(self._client) @cached_property @@ -409,10 +462,35 @@ def with_streaming_response(self) -> PrintMailResourceWithStreamingResponse: class AsyncPrintMailResource(AsyncAPIResource): @cached_property def contacts(self) -> AsyncContactsResource: + """Manage contacts that you can mail to. + + Test mode addresses will always have a + `verified` status. In live mode, they may be `verified`, `corrected`, or + `failed`. Addresses that fail to be corrected are likely undeliverable, but + you can still send to them if you want to. + + For test mode contacts, you have the ability to assert the `addressStatus` of + the contact by passing specific values to the `description` field. To receive + an `addressStatus` of `failed`, the description of the contact should be a + string with the exact value `test failed`. For an `addressStatus` value of + `corrected`, the description of the contact should be a string with the exact + value `test corrected`. + + Our address correction engine will often be able to fix missing postal/ZIP + codes, city names, and also append ZIP+4. It is SERP (Canada Post) and CASS + (USPS) certified, so you can rest assured that if an address is verified, we + can deliver to it. + """ return AsyncContactsResource(self._client) @cached_property def templates(self) -> AsyncTemplatesResource: + """Create and manage reusable HTML templates. + + A template's HTML can include + merge variables (e.g. `{{firstName}}`) and be referenced by ID when creating + letters, postcards, cheques, and self mailers. + """ return AsyncTemplatesResource(self._client) @cached_property @@ -470,24 +548,43 @@ def events(self) -> AsyncEventsResource: @cached_property def letters(self) -> AsyncLettersResource: + """Create and manage letter orders.""" return AsyncLettersResource(self._client) @cached_property def postcards(self) -> AsyncPostcardsResource: + """Create and manage postcard mailings.""" return AsyncPostcardsResource(self._client) @cached_property def bank_accounts(self) -> AsyncBankAccountsResource: + """Manage bank accounts that will be used for mailing cheques.""" return AsyncBankAccountsResource(self._client) @cached_property def cheques(self) -> AsyncChequesResource: + """Create and manage cheque orders.""" return AsyncChequesResource(self._client) @cached_property def self_mailers(self) -> AsyncSelfMailersResource: + """Create and manage self mailers.""" return AsyncSelfMailersResource(self._client) + @cached_property + def return_envelopes(self) -> AsyncReturnEnvelopesResource: + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + return AsyncReturnEnvelopesResource(self._client) + @cached_property def campaigns(self) -> AsyncCampaignsResource: """ @@ -541,6 +638,7 @@ def sub_organizations(self) -> AsyncSubOrganizationsResource: @cached_property def boxes(self) -> AsyncBoxesResource: + """Create and manage box orders.""" return AsyncBoxesResource(self._client) @cached_property @@ -650,10 +748,35 @@ def __init__(self, print_mail: PrintMailResource) -> None: @cached_property def contacts(self) -> ContactsResourceWithRawResponse: + """Manage contacts that you can mail to. + + Test mode addresses will always have a + `verified` status. In live mode, they may be `verified`, `corrected`, or + `failed`. Addresses that fail to be corrected are likely undeliverable, but + you can still send to them if you want to. + + For test mode contacts, you have the ability to assert the `addressStatus` of + the contact by passing specific values to the `description` field. To receive + an `addressStatus` of `failed`, the description of the contact should be a + string with the exact value `test failed`. For an `addressStatus` value of + `corrected`, the description of the contact should be a string with the exact + value `test corrected`. + + Our address correction engine will often be able to fix missing postal/ZIP + codes, city names, and also append ZIP+4. It is SERP (Canada Post) and CASS + (USPS) certified, so you can rest assured that if an address is verified, we + can deliver to it. + """ return ContactsResourceWithRawResponse(self._print_mail.contacts) @cached_property def templates(self) -> TemplatesResourceWithRawResponse: + """Create and manage reusable HTML templates. + + A template's HTML can include + merge variables (e.g. `{{firstName}}`) and be referenced by ID when creating + letters, postcards, cheques, and self mailers. + """ return TemplatesResourceWithRawResponse(self._print_mail.templates) @cached_property @@ -711,24 +834,43 @@ def events(self) -> EventsResourceWithRawResponse: @cached_property def letters(self) -> LettersResourceWithRawResponse: + """Create and manage letter orders.""" return LettersResourceWithRawResponse(self._print_mail.letters) @cached_property def postcards(self) -> PostcardsResourceWithRawResponse: + """Create and manage postcard mailings.""" return PostcardsResourceWithRawResponse(self._print_mail.postcards) @cached_property def bank_accounts(self) -> BankAccountsResourceWithRawResponse: + """Manage bank accounts that will be used for mailing cheques.""" return BankAccountsResourceWithRawResponse(self._print_mail.bank_accounts) @cached_property def cheques(self) -> ChequesResourceWithRawResponse: + """Create and manage cheque orders.""" return ChequesResourceWithRawResponse(self._print_mail.cheques) @cached_property def self_mailers(self) -> SelfMailersResourceWithRawResponse: + """Create and manage self mailers.""" return SelfMailersResourceWithRawResponse(self._print_mail.self_mailers) + @cached_property + def return_envelopes(self) -> ReturnEnvelopesResourceWithRawResponse: + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + return ReturnEnvelopesResourceWithRawResponse(self._print_mail.return_envelopes) + @cached_property def campaigns(self) -> CampaignsResourceWithRawResponse: """ @@ -782,6 +924,7 @@ def sub_organizations(self) -> SubOrganizationsResourceWithRawResponse: @cached_property def boxes(self) -> BoxesResourceWithRawResponse: + """Create and manage box orders.""" return BoxesResourceWithRawResponse(self._print_mail.boxes) @cached_property @@ -872,10 +1015,35 @@ def __init__(self, print_mail: AsyncPrintMailResource) -> None: @cached_property def contacts(self) -> AsyncContactsResourceWithRawResponse: + """Manage contacts that you can mail to. + + Test mode addresses will always have a + `verified` status. In live mode, they may be `verified`, `corrected`, or + `failed`. Addresses that fail to be corrected are likely undeliverable, but + you can still send to them if you want to. + + For test mode contacts, you have the ability to assert the `addressStatus` of + the contact by passing specific values to the `description` field. To receive + an `addressStatus` of `failed`, the description of the contact should be a + string with the exact value `test failed`. For an `addressStatus` value of + `corrected`, the description of the contact should be a string with the exact + value `test corrected`. + + Our address correction engine will often be able to fix missing postal/ZIP + codes, city names, and also append ZIP+4. It is SERP (Canada Post) and CASS + (USPS) certified, so you can rest assured that if an address is verified, we + can deliver to it. + """ return AsyncContactsResourceWithRawResponse(self._print_mail.contacts) @cached_property def templates(self) -> AsyncTemplatesResourceWithRawResponse: + """Create and manage reusable HTML templates. + + A template's HTML can include + merge variables (e.g. `{{firstName}}`) and be referenced by ID when creating + letters, postcards, cheques, and self mailers. + """ return AsyncTemplatesResourceWithRawResponse(self._print_mail.templates) @cached_property @@ -933,24 +1101,43 @@ def events(self) -> AsyncEventsResourceWithRawResponse: @cached_property def letters(self) -> AsyncLettersResourceWithRawResponse: + """Create and manage letter orders.""" return AsyncLettersResourceWithRawResponse(self._print_mail.letters) @cached_property def postcards(self) -> AsyncPostcardsResourceWithRawResponse: + """Create and manage postcard mailings.""" return AsyncPostcardsResourceWithRawResponse(self._print_mail.postcards) @cached_property def bank_accounts(self) -> AsyncBankAccountsResourceWithRawResponse: + """Manage bank accounts that will be used for mailing cheques.""" return AsyncBankAccountsResourceWithRawResponse(self._print_mail.bank_accounts) @cached_property def cheques(self) -> AsyncChequesResourceWithRawResponse: + """Create and manage cheque orders.""" return AsyncChequesResourceWithRawResponse(self._print_mail.cheques) @cached_property def self_mailers(self) -> AsyncSelfMailersResourceWithRawResponse: + """Create and manage self mailers.""" return AsyncSelfMailersResourceWithRawResponse(self._print_mail.self_mailers) + @cached_property + def return_envelopes(self) -> AsyncReturnEnvelopesResourceWithRawResponse: + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + return AsyncReturnEnvelopesResourceWithRawResponse(self._print_mail.return_envelopes) + @cached_property def campaigns(self) -> AsyncCampaignsResourceWithRawResponse: """ @@ -1004,6 +1191,7 @@ def sub_organizations(self) -> AsyncSubOrganizationsResourceWithRawResponse: @cached_property def boxes(self) -> AsyncBoxesResourceWithRawResponse: + """Create and manage box orders.""" return AsyncBoxesResourceWithRawResponse(self._print_mail.boxes) @cached_property @@ -1094,10 +1282,35 @@ def __init__(self, print_mail: PrintMailResource) -> None: @cached_property def contacts(self) -> ContactsResourceWithStreamingResponse: + """Manage contacts that you can mail to. + + Test mode addresses will always have a + `verified` status. In live mode, they may be `verified`, `corrected`, or + `failed`. Addresses that fail to be corrected are likely undeliverable, but + you can still send to them if you want to. + + For test mode contacts, you have the ability to assert the `addressStatus` of + the contact by passing specific values to the `description` field. To receive + an `addressStatus` of `failed`, the description of the contact should be a + string with the exact value `test failed`. For an `addressStatus` value of + `corrected`, the description of the contact should be a string with the exact + value `test corrected`. + + Our address correction engine will often be able to fix missing postal/ZIP + codes, city names, and also append ZIP+4. It is SERP (Canada Post) and CASS + (USPS) certified, so you can rest assured that if an address is verified, we + can deliver to it. + """ return ContactsResourceWithStreamingResponse(self._print_mail.contacts) @cached_property def templates(self) -> TemplatesResourceWithStreamingResponse: + """Create and manage reusable HTML templates. + + A template's HTML can include + merge variables (e.g. `{{firstName}}`) and be referenced by ID when creating + letters, postcards, cheques, and self mailers. + """ return TemplatesResourceWithStreamingResponse(self._print_mail.templates) @cached_property @@ -1155,24 +1368,43 @@ def events(self) -> EventsResourceWithStreamingResponse: @cached_property def letters(self) -> LettersResourceWithStreamingResponse: + """Create and manage letter orders.""" return LettersResourceWithStreamingResponse(self._print_mail.letters) @cached_property def postcards(self) -> PostcardsResourceWithStreamingResponse: + """Create and manage postcard mailings.""" return PostcardsResourceWithStreamingResponse(self._print_mail.postcards) @cached_property def bank_accounts(self) -> BankAccountsResourceWithStreamingResponse: + """Manage bank accounts that will be used for mailing cheques.""" return BankAccountsResourceWithStreamingResponse(self._print_mail.bank_accounts) @cached_property def cheques(self) -> ChequesResourceWithStreamingResponse: + """Create and manage cheque orders.""" return ChequesResourceWithStreamingResponse(self._print_mail.cheques) @cached_property def self_mailers(self) -> SelfMailersResourceWithStreamingResponse: + """Create and manage self mailers.""" return SelfMailersResourceWithStreamingResponse(self._print_mail.self_mailers) + @cached_property + def return_envelopes(self) -> ReturnEnvelopesResourceWithStreamingResponse: + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + return ReturnEnvelopesResourceWithStreamingResponse(self._print_mail.return_envelopes) + @cached_property def campaigns(self) -> CampaignsResourceWithStreamingResponse: """ @@ -1226,6 +1458,7 @@ def sub_organizations(self) -> SubOrganizationsResourceWithStreamingResponse: @cached_property def boxes(self) -> BoxesResourceWithStreamingResponse: + """Create and manage box orders.""" return BoxesResourceWithStreamingResponse(self._print_mail.boxes) @cached_property @@ -1316,10 +1549,35 @@ def __init__(self, print_mail: AsyncPrintMailResource) -> None: @cached_property def contacts(self) -> AsyncContactsResourceWithStreamingResponse: + """Manage contacts that you can mail to. + + Test mode addresses will always have a + `verified` status. In live mode, they may be `verified`, `corrected`, or + `failed`. Addresses that fail to be corrected are likely undeliverable, but + you can still send to them if you want to. + + For test mode contacts, you have the ability to assert the `addressStatus` of + the contact by passing specific values to the `description` field. To receive + an `addressStatus` of `failed`, the description of the contact should be a + string with the exact value `test failed`. For an `addressStatus` value of + `corrected`, the description of the contact should be a string with the exact + value `test corrected`. + + Our address correction engine will often be able to fix missing postal/ZIP + codes, city names, and also append ZIP+4. It is SERP (Canada Post) and CASS + (USPS) certified, so you can rest assured that if an address is verified, we + can deliver to it. + """ return AsyncContactsResourceWithStreamingResponse(self._print_mail.contacts) @cached_property def templates(self) -> AsyncTemplatesResourceWithStreamingResponse: + """Create and manage reusable HTML templates. + + A template's HTML can include + merge variables (e.g. `{{firstName}}`) and be referenced by ID when creating + letters, postcards, cheques, and self mailers. + """ return AsyncTemplatesResourceWithStreamingResponse(self._print_mail.templates) @cached_property @@ -1377,24 +1635,43 @@ def events(self) -> AsyncEventsResourceWithStreamingResponse: @cached_property def letters(self) -> AsyncLettersResourceWithStreamingResponse: + """Create and manage letter orders.""" return AsyncLettersResourceWithStreamingResponse(self._print_mail.letters) @cached_property def postcards(self) -> AsyncPostcardsResourceWithStreamingResponse: + """Create and manage postcard mailings.""" return AsyncPostcardsResourceWithStreamingResponse(self._print_mail.postcards) @cached_property def bank_accounts(self) -> AsyncBankAccountsResourceWithStreamingResponse: + """Manage bank accounts that will be used for mailing cheques.""" return AsyncBankAccountsResourceWithStreamingResponse(self._print_mail.bank_accounts) @cached_property def cheques(self) -> AsyncChequesResourceWithStreamingResponse: + """Create and manage cheque orders.""" return AsyncChequesResourceWithStreamingResponse(self._print_mail.cheques) @cached_property def self_mailers(self) -> AsyncSelfMailersResourceWithStreamingResponse: + """Create and manage self mailers.""" return AsyncSelfMailersResourceWithStreamingResponse(self._print_mail.self_mailers) + @cached_property + def return_envelopes(self) -> AsyncReturnEnvelopesResourceWithStreamingResponse: + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + return AsyncReturnEnvelopesResourceWithStreamingResponse(self._print_mail.return_envelopes) + @cached_property def campaigns(self) -> AsyncCampaignsResourceWithStreamingResponse: """ @@ -1448,6 +1725,7 @@ def sub_organizations(self) -> AsyncSubOrganizationsResourceWithStreamingRespons @cached_property def boxes(self) -> AsyncBoxesResourceWithStreamingResponse: + """Create and manage box orders.""" return AsyncBoxesResourceWithStreamingResponse(self._print_mail.boxes) @cached_property diff --git a/src/postgrid/resources/print_mail/return_envelopes/__init__.py b/src/postgrid/resources/print_mail/return_envelopes/__init__.py new file mode 100644 index 0000000..22ac9c0 --- /dev/null +++ b/src/postgrid/resources/print_mail/return_envelopes/__init__.py @@ -0,0 +1,33 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from .orders import ( + OrdersResource, + AsyncOrdersResource, + OrdersResourceWithRawResponse, + AsyncOrdersResourceWithRawResponse, + OrdersResourceWithStreamingResponse, + AsyncOrdersResourceWithStreamingResponse, +) +from .return_envelopes import ( + ReturnEnvelopesResource, + AsyncReturnEnvelopesResource, + ReturnEnvelopesResourceWithRawResponse, + AsyncReturnEnvelopesResourceWithRawResponse, + ReturnEnvelopesResourceWithStreamingResponse, + AsyncReturnEnvelopesResourceWithStreamingResponse, +) + +__all__ = [ + "OrdersResource", + "AsyncOrdersResource", + "OrdersResourceWithRawResponse", + "AsyncOrdersResourceWithRawResponse", + "OrdersResourceWithStreamingResponse", + "AsyncOrdersResourceWithStreamingResponse", + "ReturnEnvelopesResource", + "AsyncReturnEnvelopesResource", + "ReturnEnvelopesResourceWithRawResponse", + "AsyncReturnEnvelopesResourceWithRawResponse", + "ReturnEnvelopesResourceWithStreamingResponse", + "AsyncReturnEnvelopesResourceWithStreamingResponse", +] diff --git a/src/postgrid/resources/print_mail/return_envelopes/orders.py b/src/postgrid/resources/print_mail/return_envelopes/orders.py new file mode 100644 index 0000000..31c03b9 --- /dev/null +++ b/src/postgrid/resources/print_mail/return_envelopes/orders.py @@ -0,0 +1,652 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, List +from typing_extensions import Literal + +import httpx + +from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ...._utils import path_template, maybe_transform, async_maybe_transform +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ....pagination import SyncSkipLimit, AsyncSkipLimit +from ...._base_client import AsyncPaginator, make_request_options +from ....types.print_mail.return_envelopes import ( + order_list_params, + order_cancel_params, + order_create_params, + order_retrieve_params, +) +from ....types.print_mail.return_envelopes.return_envelope_order import ReturnEnvelopeOrder + +__all__ = ["OrdersResource", "AsyncOrdersResource"] + + +class OrdersResource(SyncAPIResource): + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + + @cached_property + def with_raw_response(self) -> OrdersResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/postgrid/postgrid-python#accessing-raw-response-data-eg-headers + """ + return OrdersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> OrdersResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/postgrid/postgrid-python#with_streaming_response + """ + return OrdersResourceWithStreamingResponse(self) + + def create( + self, + id: str, + *, + quantity_ordered: int, + description: str | Omit = omit, + metadata: Dict[str, object] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ReturnEnvelopeOrder: + """Creates a batch order of return envelopes. + + The minimum order quantity is 5000. + + Args: + quantity_ordered: The quantity of return envelopes ordered. Minimum 5000. + + description: An optional string describing this resource. Will be visible in the API and the + dashboard. + + metadata: See the section on Metadata. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._post( + path_template("/print-mail/v1/return_envelopes/{id}/orders", id=id), + body=maybe_transform( + { + "quantity_ordered": quantity_ordered, + "description": description, + "metadata": metadata, + }, + order_create_params.OrderCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ReturnEnvelopeOrder, + ) + + def retrieve( + self, + order_id: str, + *, + id: str, + expand: List[Literal["returnEnvelope"]] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ReturnEnvelopeOrder: + """ + Gets a specific return envelope order by return envelope ID as `id` and return + envelope order ID as `orderID`. + + Args: + expand: Pass `expand[]=returnEnvelope` to expand the order's `returnEnvelope` field into + the full return envelope object. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + if not order_id: + raise ValueError(f"Expected a non-empty value for `order_id` but received {order_id!r}") + return self._get( + path_template("/print-mail/v1/return_envelopes/{id}/orders/{order_id}", id=id, order_id=order_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"expand": expand}, order_retrieve_params.OrderRetrieveParams), + ), + cast_to=ReturnEnvelopeOrder, + ) + + def list( + self, + id: str, + *, + limit: int | Omit = omit, + search: str | Omit = omit, + skip: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SyncSkipLimit[ReturnEnvelopeOrder]: + """ + Gets a list of orders for the return envelope by `id`. + + Args: + search: You can supply any string to help narrow down the list of resources. For + example, if you pass `"New York"` (quoted), it will return resources that have + that string present somewhere in their response. Alternatively, you can supply a + structured search query. See the documentation on `StructuredSearchQuery` for + more details. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get_api_list( + path_template("/print-mail/v1/return_envelopes/{id}/orders", id=id), + page=SyncSkipLimit[ReturnEnvelopeOrder], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "search": search, + "skip": skip, + }, + order_list_params.OrderListParams, + ), + ), + model=ReturnEnvelopeOrder, + ) + + def cancel( + self, + order_id: str, + *, + id: str, + expand: List[Literal["returnEnvelope"]] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ReturnEnvelopeOrder: + """ + Cancels the return envelope order by `orderID` for the return envelope by `id`. + Note that this operation cannot be undone. + + Args: + expand: Pass `expand[]=returnEnvelope` to expand the order's `returnEnvelope` field into + the full return envelope object. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + if not order_id: + raise ValueError(f"Expected a non-empty value for `order_id` but received {order_id!r}") + return self._delete( + path_template("/print-mail/v1/return_envelopes/{id}/orders/{order_id}", id=id, order_id=order_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform({"expand": expand}, order_cancel_params.OrderCancelParams), + ), + cast_to=ReturnEnvelopeOrder, + ) + + def fill( + self, + order_id: str, + *, + id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ReturnEnvelopeOrder: + """ + Fills the return envelope order by `orderID` for the return envelope by `id`. + This is only available in test mode and can be used to simulate how a live order + would be filled. + + Note: this will fail with a `return_envelope_order_cannot_fill_error` if the + order's status is not `placed`. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + if not order_id: + raise ValueError(f"Expected a non-empty value for `order_id` but received {order_id!r}") + return self._post( + path_template("/print-mail/v1/return_envelopes/{id}/orders/{order_id}/fills", id=id, order_id=order_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ReturnEnvelopeOrder, + ) + + +class AsyncOrdersResource(AsyncAPIResource): + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + + @cached_property + def with_raw_response(self) -> AsyncOrdersResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/postgrid/postgrid-python#accessing-raw-response-data-eg-headers + """ + return AsyncOrdersResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncOrdersResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/postgrid/postgrid-python#with_streaming_response + """ + return AsyncOrdersResourceWithStreamingResponse(self) + + async def create( + self, + id: str, + *, + quantity_ordered: int, + description: str | Omit = omit, + metadata: Dict[str, object] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ReturnEnvelopeOrder: + """Creates a batch order of return envelopes. + + The minimum order quantity is 5000. + + Args: + quantity_ordered: The quantity of return envelopes ordered. Minimum 5000. + + description: An optional string describing this resource. Will be visible in the API and the + dashboard. + + metadata: See the section on Metadata. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._post( + path_template("/print-mail/v1/return_envelopes/{id}/orders", id=id), + body=await async_maybe_transform( + { + "quantity_ordered": quantity_ordered, + "description": description, + "metadata": metadata, + }, + order_create_params.OrderCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ReturnEnvelopeOrder, + ) + + async def retrieve( + self, + order_id: str, + *, + id: str, + expand: List[Literal["returnEnvelope"]] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ReturnEnvelopeOrder: + """ + Gets a specific return envelope order by return envelope ID as `id` and return + envelope order ID as `orderID`. + + Args: + expand: Pass `expand[]=returnEnvelope` to expand the order's `returnEnvelope` field into + the full return envelope object. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + if not order_id: + raise ValueError(f"Expected a non-empty value for `order_id` but received {order_id!r}") + return await self._get( + path_template("/print-mail/v1/return_envelopes/{id}/orders/{order_id}", id=id, order_id=order_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"expand": expand}, order_retrieve_params.OrderRetrieveParams), + ), + cast_to=ReturnEnvelopeOrder, + ) + + def list( + self, + id: str, + *, + limit: int | Omit = omit, + search: str | Omit = omit, + skip: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncPaginator[ReturnEnvelopeOrder, AsyncSkipLimit[ReturnEnvelopeOrder]]: + """ + Gets a list of orders for the return envelope by `id`. + + Args: + search: You can supply any string to help narrow down the list of resources. For + example, if you pass `"New York"` (quoted), it will return resources that have + that string present somewhere in their response. Alternatively, you can supply a + structured search query. See the documentation on `StructuredSearchQuery` for + more details. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get_api_list( + path_template("/print-mail/v1/return_envelopes/{id}/orders", id=id), + page=AsyncSkipLimit[ReturnEnvelopeOrder], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "search": search, + "skip": skip, + }, + order_list_params.OrderListParams, + ), + ), + model=ReturnEnvelopeOrder, + ) + + async def cancel( + self, + order_id: str, + *, + id: str, + expand: List[Literal["returnEnvelope"]] | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ReturnEnvelopeOrder: + """ + Cancels the return envelope order by `orderID` for the return envelope by `id`. + Note that this operation cannot be undone. + + Args: + expand: Pass `expand[]=returnEnvelope` to expand the order's `returnEnvelope` field into + the full return envelope object. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + if not order_id: + raise ValueError(f"Expected a non-empty value for `order_id` but received {order_id!r}") + return await self._delete( + path_template("/print-mail/v1/return_envelopes/{id}/orders/{order_id}", id=id, order_id=order_id), + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=await async_maybe_transform({"expand": expand}, order_cancel_params.OrderCancelParams), + ), + cast_to=ReturnEnvelopeOrder, + ) + + async def fill( + self, + order_id: str, + *, + id: str, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ReturnEnvelopeOrder: + """ + Fills the return envelope order by `orderID` for the return envelope by `id`. + This is only available in test mode and can be used to simulate how a live order + would be filled. + + Note: this will fail with a `return_envelope_order_cannot_fill_error` if the + order's status is not `placed`. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + if not order_id: + raise ValueError(f"Expected a non-empty value for `order_id` but received {order_id!r}") + return await self._post( + path_template("/print-mail/v1/return_envelopes/{id}/orders/{order_id}/fills", id=id, order_id=order_id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ReturnEnvelopeOrder, + ) + + +class OrdersResourceWithRawResponse: + def __init__(self, orders: OrdersResource) -> None: + self._orders = orders + + self.create = to_raw_response_wrapper( + orders.create, + ) + self.retrieve = to_raw_response_wrapper( + orders.retrieve, + ) + self.list = to_raw_response_wrapper( + orders.list, + ) + self.cancel = to_raw_response_wrapper( + orders.cancel, + ) + self.fill = to_raw_response_wrapper( + orders.fill, + ) + + +class AsyncOrdersResourceWithRawResponse: + def __init__(self, orders: AsyncOrdersResource) -> None: + self._orders = orders + + self.create = async_to_raw_response_wrapper( + orders.create, + ) + self.retrieve = async_to_raw_response_wrapper( + orders.retrieve, + ) + self.list = async_to_raw_response_wrapper( + orders.list, + ) + self.cancel = async_to_raw_response_wrapper( + orders.cancel, + ) + self.fill = async_to_raw_response_wrapper( + orders.fill, + ) + + +class OrdersResourceWithStreamingResponse: + def __init__(self, orders: OrdersResource) -> None: + self._orders = orders + + self.create = to_streamed_response_wrapper( + orders.create, + ) + self.retrieve = to_streamed_response_wrapper( + orders.retrieve, + ) + self.list = to_streamed_response_wrapper( + orders.list, + ) + self.cancel = to_streamed_response_wrapper( + orders.cancel, + ) + self.fill = to_streamed_response_wrapper( + orders.fill, + ) + + +class AsyncOrdersResourceWithStreamingResponse: + def __init__(self, orders: AsyncOrdersResource) -> None: + self._orders = orders + + self.create = async_to_streamed_response_wrapper( + orders.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + orders.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + orders.list, + ) + self.cancel = async_to_streamed_response_wrapper( + orders.cancel, + ) + self.fill = async_to_streamed_response_wrapper( + orders.fill, + ) diff --git a/src/postgrid/resources/print_mail/return_envelopes/return_envelopes.py b/src/postgrid/resources/print_mail/return_envelopes/return_envelopes.py new file mode 100644 index 0000000..481bcd0 --- /dev/null +++ b/src/postgrid/resources/print_mail/return_envelopes/return_envelopes.py @@ -0,0 +1,520 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict + +import httpx + +from .orders import ( + OrdersResource, + AsyncOrdersResource, + OrdersResourceWithRawResponse, + AsyncOrdersResourceWithRawResponse, + OrdersResourceWithStreamingResponse, + AsyncOrdersResourceWithStreamingResponse, +) +from ...._types import Body, Omit, Query, Headers, NotGiven, omit, not_given +from ...._utils import path_template, maybe_transform, strip_not_given, async_maybe_transform +from ...._compat import cached_property +from ...._resource import SyncAPIResource, AsyncAPIResource +from ...._response import ( + to_raw_response_wrapper, + to_streamed_response_wrapper, + async_to_raw_response_wrapper, + async_to_streamed_response_wrapper, +) +from ....pagination import SyncSkipLimit, AsyncSkipLimit +from ...._base_client import AsyncPaginator, make_request_options +from ....types.print_mail import return_envelope_list_params, return_envelope_create_params +from ....types.print_mail.return_envelope import ReturnEnvelope + +__all__ = ["ReturnEnvelopesResource", "AsyncReturnEnvelopesResource"] + + +class ReturnEnvelopesResource(SyncAPIResource): + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + + @cached_property + def orders(self) -> OrdersResource: + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + return OrdersResource(self._client) + + @cached_property + def with_raw_response(self) -> ReturnEnvelopesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/postgrid/postgrid-python#accessing-raw-response-data-eg-headers + """ + return ReturnEnvelopesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> ReturnEnvelopesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/postgrid/postgrid-python#with_streaming_response + """ + return ReturnEnvelopesResourceWithStreamingResponse(self) + + def create( + self, + *, + to: return_envelope_create_params.To, + description: str | Omit = omit, + metadata: Dict[str, object] | Omit = omit, + idempotency_key: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ReturnEnvelope: + """Creates a new return envelope. + + Note that if there is already a return envelope + for the destination contact, this will fail with a + `return_envelope_already_exists_error`. + + Args: + to: A contact ID or a contact object containing the address that will be printed + onto the return envelope. + + description: An optional string describing this resource. Will be visible in the API and the + dashboard. + + metadata: See the section on Metadata. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {**strip_not_given({"idempotency-key": idempotency_key}), **(extra_headers or {})} + return self._post( + "/print-mail/v1/return_envelopes", + body=maybe_transform( + { + "to": to, + "description": description, + "metadata": metadata, + }, + return_envelope_create_params.ReturnEnvelopeCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ReturnEnvelope, + ) + + def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ReturnEnvelope: + """Gets the information for a return envelope by `id`. + + This should be a unique + identifying string starting with `return_envelope_`. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return self._get( + path_template("/print-mail/v1/return_envelopes/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ReturnEnvelope, + ) + + def list( + self, + *, + limit: int | Omit = omit, + search: str | Omit = omit, + skip: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> SyncSkipLimit[ReturnEnvelope]: + """ + Gets a list of return envelopes for the user. + + Args: + search: You can supply any string to help narrow down the list of resources. For + example, if you pass `"New York"` (quoted), it will return resources that have + that string present somewhere in their response. Alternatively, you can supply a + structured search query. See the documentation on `StructuredSearchQuery` for + more details. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/print-mail/v1/return_envelopes", + page=SyncSkipLimit[ReturnEnvelope], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "search": search, + "skip": skip, + }, + return_envelope_list_params.ReturnEnvelopeListParams, + ), + ), + model=ReturnEnvelope, + ) + + +class AsyncReturnEnvelopesResource(AsyncAPIResource): + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + + @cached_property + def orders(self) -> AsyncOrdersResource: + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + return AsyncOrdersResource(self._client) + + @cached_property + def with_raw_response(self) -> AsyncReturnEnvelopesResourceWithRawResponse: + """ + This property can be used as a prefix for any HTTP method call to return + the raw response object instead of the parsed content. + + For more information, see https://www.github.com/postgrid/postgrid-python#accessing-raw-response-data-eg-headers + """ + return AsyncReturnEnvelopesResourceWithRawResponse(self) + + @cached_property + def with_streaming_response(self) -> AsyncReturnEnvelopesResourceWithStreamingResponse: + """ + An alternative to `.with_raw_response` that doesn't eagerly read the response body. + + For more information, see https://www.github.com/postgrid/postgrid-python#with_streaming_response + """ + return AsyncReturnEnvelopesResourceWithStreamingResponse(self) + + async def create( + self, + *, + to: return_envelope_create_params.To, + description: str | Omit = omit, + metadata: Dict[str, object] | Omit = omit, + idempotency_key: str | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ReturnEnvelope: + """Creates a new return envelope. + + Note that if there is already a return envelope + for the destination contact, this will fail with a + `return_envelope_already_exists_error`. + + Args: + to: A contact ID or a contact object containing the address that will be printed + onto the return envelope. + + description: An optional string describing this resource. Will be visible in the API and the + dashboard. + + metadata: See the section on Metadata. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + extra_headers = {**strip_not_given({"idempotency-key": idempotency_key}), **(extra_headers or {})} + return await self._post( + "/print-mail/v1/return_envelopes", + body=await async_maybe_transform( + { + "to": to, + "description": description, + "metadata": metadata, + }, + return_envelope_create_params.ReturnEnvelopeCreateParams, + ), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ReturnEnvelope, + ) + + async def retrieve( + self, + id: str, + *, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> ReturnEnvelope: + """Gets the information for a return envelope by `id`. + + This should be a unique + identifying string starting with `return_envelope_`. + + Args: + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + if not id: + raise ValueError(f"Expected a non-empty value for `id` but received {id!r}") + return await self._get( + path_template("/print-mail/v1/return_envelopes/{id}", id=id), + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=ReturnEnvelope, + ) + + def list( + self, + *, + limit: int | Omit = omit, + search: str | Omit = omit, + skip: int | Omit = omit, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = not_given, + ) -> AsyncPaginator[ReturnEnvelope, AsyncSkipLimit[ReturnEnvelope]]: + """ + Gets a list of return envelopes for the user. + + Args: + search: You can supply any string to help narrow down the list of resources. For + example, if you pass `"New York"` (quoted), it will return resources that have + that string present somewhere in their response. Alternatively, you can supply a + structured search query. See the documentation on `StructuredSearchQuery` for + more details. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + return self._get_api_list( + "/print-mail/v1/return_envelopes", + page=AsyncSkipLimit[ReturnEnvelope], + options=make_request_options( + extra_headers=extra_headers, + extra_query=extra_query, + extra_body=extra_body, + timeout=timeout, + query=maybe_transform( + { + "limit": limit, + "search": search, + "skip": skip, + }, + return_envelope_list_params.ReturnEnvelopeListParams, + ), + ), + model=ReturnEnvelope, + ) + + +class ReturnEnvelopesResourceWithRawResponse: + def __init__(self, return_envelopes: ReturnEnvelopesResource) -> None: + self._return_envelopes = return_envelopes + + self.create = to_raw_response_wrapper( + return_envelopes.create, + ) + self.retrieve = to_raw_response_wrapper( + return_envelopes.retrieve, + ) + self.list = to_raw_response_wrapper( + return_envelopes.list, + ) + + @cached_property + def orders(self) -> OrdersResourceWithRawResponse: + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + return OrdersResourceWithRawResponse(self._return_envelopes.orders) + + +class AsyncReturnEnvelopesResourceWithRawResponse: + def __init__(self, return_envelopes: AsyncReturnEnvelopesResource) -> None: + self._return_envelopes = return_envelopes + + self.create = async_to_raw_response_wrapper( + return_envelopes.create, + ) + self.retrieve = async_to_raw_response_wrapper( + return_envelopes.retrieve, + ) + self.list = async_to_raw_response_wrapper( + return_envelopes.list, + ) + + @cached_property + def orders(self) -> AsyncOrdersResourceWithRawResponse: + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + return AsyncOrdersResourceWithRawResponse(self._return_envelopes.orders) + + +class ReturnEnvelopesResourceWithStreamingResponse: + def __init__(self, return_envelopes: ReturnEnvelopesResource) -> None: + self._return_envelopes = return_envelopes + + self.create = to_streamed_response_wrapper( + return_envelopes.create, + ) + self.retrieve = to_streamed_response_wrapper( + return_envelopes.retrieve, + ) + self.list = to_streamed_response_wrapper( + return_envelopes.list, + ) + + @cached_property + def orders(self) -> OrdersResourceWithStreamingResponse: + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + return OrdersResourceWithStreamingResponse(self._return_envelopes.orders) + + +class AsyncReturnEnvelopesResourceWithStreamingResponse: + def __init__(self, return_envelopes: AsyncReturnEnvelopesResource) -> None: + self._return_envelopes = return_envelopes + + self.create = async_to_streamed_response_wrapper( + return_envelopes.create, + ) + self.retrieve = async_to_streamed_response_wrapper( + return_envelopes.retrieve, + ) + self.list = async_to_streamed_response_wrapper( + return_envelopes.list, + ) + + @cached_property + def orders(self) -> AsyncOrdersResourceWithStreamingResponse: + """ + You can use the return envelopes API to create and manage return envelopes. + These are envelopes that are sent along with your mail (if specified) and + allow your recipients to send mail to a particular address without having to + purchase their own envelopes/stamps. + + Note that you must order return envelopes and wait for the order to be + filled before you can use them. You can manage these return envelope orders + via the API as well as the dashboard. + """ + return AsyncOrdersResourceWithStreamingResponse(self._return_envelopes.orders) diff --git a/src/postgrid/resources/print_mail/self_mailers.py b/src/postgrid/resources/print_mail/self_mailers.py index 8a6f771..92fb5e0 100644 --- a/src/postgrid/resources/print_mail/self_mailers.py +++ b/src/postgrid/resources/print_mail/self_mailers.py @@ -28,6 +28,8 @@ class SelfMailersResource(SyncAPIResource): + """Create and manage self mailers.""" + @cached_property def with_raw_response(self) -> SelfMailersResourceWithRawResponse: """ @@ -733,6 +735,8 @@ def retrieve_url( class AsyncSelfMailersResource(AsyncAPIResource): + """Create and manage self mailers.""" + @cached_property def with_raw_response(self) -> AsyncSelfMailersResourceWithRawResponse: """ diff --git a/src/postgrid/resources/print_mail/templates.py b/src/postgrid/resources/print_mail/templates.py index 3fcecaa..6814611 100644 --- a/src/postgrid/resources/print_mail/templates.py +++ b/src/postgrid/resources/print_mail/templates.py @@ -26,6 +26,13 @@ class TemplatesResource(SyncAPIResource): + """Create and manage reusable HTML templates. + + A template's HTML can include + merge variables (e.g. `{{firstName}}`) and be referenced by ID when creating + letters, postcards, cheques, and self mailers. + """ + @cached_property def with_raw_response(self) -> TemplatesResourceWithRawResponse: """ @@ -266,6 +273,13 @@ def delete( class AsyncTemplatesResource(AsyncAPIResource): + """Create and manage reusable HTML templates. + + A template's HTML can include + merge variables (e.g. `{{firstName}}`) and be referenced by ID when creating + letters, postcards, cheques, and self mailers. + """ + @cached_property def with_raw_response(self) -> AsyncTemplatesResourceWithRawResponse: """ diff --git a/src/postgrid/types/__init__.py b/src/postgrid/types/__init__.py index 0853cc0..fb68b60 100644 --- a/src/postgrid/types/__init__.py +++ b/src/postgrid/types/__init__.py @@ -4,7 +4,13 @@ from .errors import Errors as Errors from .status import Status as Status +from .addver_list import AddverList as AddverList +from .bulk_verification_list_params import BulkVerificationListParams as BulkVerificationListParams +from .bulk_verification_list_response import BulkVerificationListResponse as BulkVerificationListResponse +from .bulk_verification_upload_params import BulkVerificationUploadParams as BulkVerificationUploadParams +from .bulk_verification_upload_response import BulkVerificationUploadResponse as BulkVerificationUploadResponse from .address_verification_verify_params import AddressVerificationVerifyParams as AddressVerificationVerifyParams +from .bulk_verification_retrieve_response import BulkVerificationRetrieveResponse as BulkVerificationRetrieveResponse from .address_verification_verify_response import AddressVerificationVerifyResponse as AddressVerificationVerifyResponse from .intl_address_verification_verify_params import ( IntlAddressVerificationVerifyParams as IntlAddressVerificationVerifyParams, diff --git a/src/postgrid/types/address_verification_get_lookup_info_response.py b/src/postgrid/types/address_verification_get_lookup_info_response.py index 9948741..65888b4 100644 --- a/src/postgrid/types/address_verification_get_lookup_info_response.py +++ b/src/postgrid/types/address_verification_get_lookup_info_response.py @@ -17,6 +17,9 @@ class Data(BaseModel): indicates an unlimited plan. """ + subscribed: bool + """Whether the organization is on a paid (subscribed) plan.""" + used: int """The number of lookups consumed in the current billing period.""" diff --git a/src/postgrid/types/addver_list.py b/src/postgrid/types/addver_list.py new file mode 100644 index 0000000..d3a4915 --- /dev/null +++ b/src/postgrid/types/addver_list.py @@ -0,0 +1,170 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from datetime import datetime + +from pydantic import Field as FieldInfo + +from .._models import BaseModel + +__all__ = ["AddverList", "Mappings", "Metadata", "MetadataStatusCount"] + + +class Mappings(BaseModel): + """The mapping of your CSV column names to PostGrid address fields. + + Each value is + the name of a column in your uploaded file. + """ + + line1: str + """The column containing the first line of each address. + + If your entire address is in a single column, specify only this mapping. + """ + + city: Optional[str] = None + """The column containing the city of each address.""" + + country: Optional[str] = None + """ + The column containing the 2-letter ISO country code of each address (e.g. `US`, + not `United States`). + """ + + first_name: Optional[str] = FieldInfo(alias="firstName", default=None) + """The column containing the first name of the person at each address. + + Only used when NCOA is run. + """ + + full_name: Optional[str] = FieldInfo(alias="fullName", default=None) + """The column containing the full name of the person at each address. + + Can be supplied instead of `firstName` and `lastName`. Only used when NCOA or + CCOA is run. + """ + + last_name: Optional[str] = FieldInfo(alias="lastName", default=None) + """The column containing the last name of the person at each address. + + Only used when NCOA is run. + """ + + line2: Optional[str] = None + """The column containing the second line of each address.""" + + postal_or_zip: Optional[str] = FieldInfo(alias="postalOrZip", default=None) + """The column containing the postal or ZIP code of each address.""" + + province_or_state: Optional[str] = FieldInfo(alias="provinceOrState", default=None) + """The column containing the province or state of each address.""" + + +class MetadataStatusCount(BaseModel): + """The number of addresses by resulting verification status.""" + + corrected: Optional[int] = None + + failed: Optional[int] = None + + verified: Optional[int] = None + + +class Metadata(BaseModel): + """Additional metadata about the list, including a count of each status.""" + + status_count: Optional[MetadataStatusCount] = FieldInfo(alias="statusCount", default=None) + """The number of addresses by resulting verification status.""" + + +class AddverList(BaseModel): + """ + A bulk address verification list — an uploaded CSV file of addresses and its + processing state. + """ + + id: str + """A unique ID prefixed with `addver_list_`.""" + + cost: int + """The cost charged for processing this list.""" + + count: int + """The number of addresses in the uploaded file.""" + + created_at: datetime = FieldInfo(alias="createdAt") + """The UTC time at which this list was created.""" + + file: str + """A signed URL to the uploaded input CSV file.""" + + mappings: Mappings + """The mapping of your CSV column names to PostGrid address fields. + + Each value is the name of a column in your uploaded file. + """ + + name: str + """The name supplied for the list. + + This only affects what is displayed in the dashboard. + """ + + organization: str + """The ID of the organization that owns this list.""" + + status: str + """The processing status of the list, e.g. + + `pending`, `processing`, or `processed`. + """ + + updated_at: datetime = FieldInfo(alias="updatedAt") + """The UTC time at which this list was last updated.""" + + use_geocode: bool = FieldInfo(alias="useGeocode") + """Whether geocoding (latitude/longitude) output was requested.""" + + use_intl_verification: bool = FieldInfo(alias="useIntlVerification") + """Whether international (outside US & Canada) verification was requested.""" + + use_proper_case: bool = FieldInfo(alias="useProperCase") + """Whether Proper Case output was requested.""" + + user: str + """The ID of the user that created this list.""" + + default_country: Optional[str] = FieldInfo(alias="defaultCountry", default=None) + """ + The ISO 2-letter country code used as the fallback when a row is missing a + country. Not returned for lists uploaded without one, e.g. lists which map the + entire address into `line1`. + """ + + metadata: Optional[Metadata] = None + """Additional metadata about the list, including a count of each status.""" + + num_invalid_rows: Optional[int] = FieldInfo(alias="numInvalidRows", default=None) + """The number of invalid or skipped rows in the uploaded file. + + May be omitted on lists created before this field was introduced. + """ + + result: Optional[str] = None + """A signed URL to the processed output CSV file. + + Present once the list has finished processing. + """ + + run_ccoa: Optional[bool] = FieldInfo(alias="runCCOA", default=None) + """Whether CCOA (Canada Post change of address) was requested. + + May be omitted on lists created before COA support was introduced. + """ + + run_ncoa: Optional[bool] = FieldInfo(alias="runNCOA", default=None) + """Whether NCOA (US National Change of Address) was requested. + + May be omitted on lists created before COA support was introduced. + """ diff --git a/src/postgrid/types/bulk_verification_list_params.py b/src/postgrid/types/bulk_verification_list_params.py new file mode 100644 index 0000000..4055290 --- /dev/null +++ b/src/postgrid/types/bulk_verification_list_params.py @@ -0,0 +1,15 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["BulkVerificationListParams"] + + +class BulkVerificationListParams(TypedDict, total=False): + limit: int + """The maximum number of lists to return.""" + + skip: int + """The number of lists to skip past, for pagination.""" diff --git a/src/postgrid/types/bulk_verification_list_response.py b/src/postgrid/types/bulk_verification_list_response.py new file mode 100644 index 0000000..ba86bcb --- /dev/null +++ b/src/postgrid/types/bulk_verification_list_response.py @@ -0,0 +1,28 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List +from typing_extensions import Literal + +from .._models import BaseModel +from .addver_list import AddverList + +__all__ = ["BulkVerificationListResponse", "Data"] + + +class Data(BaseModel): + """A list of bulk verification lists.""" + + count: int + """The total number of lists.""" + + data: List[AddverList] + """The requested lists.""" + + +class BulkVerificationListResponse(BaseModel): + data: Data + """A list of bulk verification lists.""" + + message: str + + status: Literal["success", "error"] diff --git a/src/postgrid/types/bulk_verification_retrieve_response.py b/src/postgrid/types/bulk_verification_retrieve_response.py new file mode 100644 index 0000000..9c49569 --- /dev/null +++ b/src/postgrid/types/bulk_verification_retrieve_response.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal + +from .._models import BaseModel +from .addver_list import AddverList + +__all__ = ["BulkVerificationRetrieveResponse"] + + +class BulkVerificationRetrieveResponse(BaseModel): + data: AddverList + """ + A bulk address verification list — an uploaded CSV file of addresses and its + processing state. + """ + + message: str + + status: Literal["success", "error"] diff --git a/src/postgrid/types/bulk_verification_upload_params.py b/src/postgrid/types/bulk_verification_upload_params.py new file mode 100644 index 0000000..a9fd8f7 --- /dev/null +++ b/src/postgrid/types/bulk_verification_upload_params.py @@ -0,0 +1,105 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import Required, Annotated, TypedDict + +from .._types import FileTypes +from .._utils import PropertyInfo + +__all__ = ["BulkVerificationUploadParams", "Mappings"] + + +class BulkVerificationUploadParams(TypedDict, total=False): + file: Required[FileTypes] + + mappings: Required[Mappings] + """The mapping of your CSV column names to PostGrid address fields. + + Each value is the name of a column in your uploaded file. + """ + + name: Required[str] + """A name for the uploaded list. + + This only affects what is displayed in the dashboard. + """ + + default_country: Annotated[str, PropertyInfo(alias="defaultCountry")] + """ + An ISO 2-letter country code used as the fallback when a row is missing a value + in the `country` column. + """ + + run_ccoa: Annotated[bool, PropertyInfo(alias="runCCOA")] + """Whether to run CCOA (Canada Post change of address) on the list. + + Note that a list cannot run both NCOA and CCOA — split mixed US/Canadian files + into separate lists. + """ + + run_ncoa: Annotated[bool, PropertyInfo(alias="runNCOA")] + """Whether to run NCOA (US National Change of Address) on the list.""" + + use_geocode: Annotated[bool, PropertyInfo(alias="useGeocode")] + """ + Whether to append geographical location information (latitude, longitude) to + your output. Bulk geocoding must be enabled by contacting support. + """ + + use_intl_verification: Annotated[bool, PropertyInfo(alias="useIntlVerification")] + """Whether to perform international (outside US & Canada) verification.""" + + use_proper_case: Annotated[bool, PropertyInfo(alias="useProperCase")] + """Whether to return addresses in Proper Case.""" + + +class Mappings(TypedDict, total=False): + """The mapping of your CSV column names to PostGrid address fields. + + Each value is + the name of a column in your uploaded file. + """ + + line1: Required[str] + """The column containing the first line of each address. + + If your entire address is in a single column, specify only this mapping. + """ + + city: str + """The column containing the city of each address.""" + + country: str + """ + The column containing the 2-letter ISO country code of each address (e.g. `US`, + not `United States`). + """ + + first_name: Annotated[str, PropertyInfo(alias="firstName")] + """The column containing the first name of the person at each address. + + Only used when NCOA is run. + """ + + full_name: Annotated[str, PropertyInfo(alias="fullName")] + """The column containing the full name of the person at each address. + + Can be supplied instead of `firstName` and `lastName`. Only used when NCOA or + CCOA is run. + """ + + last_name: Annotated[str, PropertyInfo(alias="lastName")] + """The column containing the last name of the person at each address. + + Only used when NCOA is run. + """ + + line2: str + """The column containing the second line of each address.""" + + postal_or_zip: Annotated[str, PropertyInfo(alias="postalOrZip")] + """The column containing the postal or ZIP code of each address.""" + + province_or_state: Annotated[str, PropertyInfo(alias="provinceOrState")] + """The column containing the province or state of each address.""" diff --git a/src/postgrid/types/bulk_verification_upload_response.py b/src/postgrid/types/bulk_verification_upload_response.py new file mode 100644 index 0000000..719037e --- /dev/null +++ b/src/postgrid/types/bulk_verification_upload_response.py @@ -0,0 +1,20 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing_extensions import Literal + +from .._models import BaseModel +from .addver_list import AddverList + +__all__ = ["BulkVerificationUploadResponse"] + + +class BulkVerificationUploadResponse(BaseModel): + data: AddverList + """ + A bulk address verification list — an uploaded CSV file of addresses and its + processing state. + """ + + message: str + + status: Literal["success", "error"] diff --git a/src/postgrid/types/intl_address_verification_get_autocomplete_advanced_previews_response.py b/src/postgrid/types/intl_address_verification_get_autocomplete_advanced_previews_response.py index bc43848..7990db4 100644 --- a/src/postgrid/types/intl_address_verification_get_autocomplete_advanced_previews_response.py +++ b/src/postgrid/types/intl_address_verification_get_autocomplete_advanced_previews_response.py @@ -17,9 +17,9 @@ class Data(BaseModel): id: Optional[str] = None """The unique identifier for this result. - Pass this to `POST /completions` to retrieve the full address. If the `type` is - `Container`, pass it as the `container` parameter to `GET /completions` to drill - down further. + If the result is a fully resolvable address (`type` is `Address`), pass this to + `POST /completions` to retrieve the full address. Otherwise, pass it as the + `container` query parameter to `GET /completions` to drill down further. """ description: Optional[str] = None diff --git a/src/postgrid/types/intl_address_verification_get_autocomplete_previews_response.py b/src/postgrid/types/intl_address_verification_get_autocomplete_previews_response.py index b3c4b4d..4e0f14a 100644 --- a/src/postgrid/types/intl_address_verification_get_autocomplete_previews_response.py +++ b/src/postgrid/types/intl_address_verification_get_autocomplete_previews_response.py @@ -17,9 +17,9 @@ class Data(BaseModel): id: Optional[str] = None """The unique identifier for this result. - Pass this to `POST /completions` to retrieve the full address. If the `type` is - `Container`, pass it as the `container` parameter to `GET /completions` to drill - down further. + If the result is a fully resolvable address (`type` is `Address`), pass this to + `POST /completions` to retrieve the full address. Otherwise, pass it as the + `container` query parameter to `GET /completions` to drill down further. """ description: Optional[str] = None diff --git a/src/postgrid/types/print_mail/__init__.py b/src/postgrid/types/print_mail/__init__.py index 509089b..f71b44c 100644 --- a/src/postgrid/types/print_mail/__init__.py +++ b/src/postgrid/types/print_mail/__init__.py @@ -21,6 +21,7 @@ from .mailing_list import MailingList as MailingList from .plastic_card import PlasticCard as PlasticCard from .box_list_params import BoxListParams as BoxListParams +from .return_envelope import ReturnEnvelope as ReturnEnvelope from .deleted_response import DeletedResponse as DeletedResponse from .sub_organization import SubOrganization as SubOrganization from .address_placement import AddressPlacement as AddressPlacement @@ -90,6 +91,7 @@ from .bank_account_create_params import BankAccountCreateParams as BankAccountCreateParams from .mailing_list_create_params import MailingListCreateParams as MailingListCreateParams from .mailing_list_update_params import MailingListUpdateParams as MailingListUpdateParams +from .return_envelope_list_params import ReturnEnvelopeListParams as ReturnEnvelopeListParams from .snap_pack_retrieve_response import SnapPackRetrieveResponse as SnapPackRetrieveResponse from .virtual_mailbox_list_params import VirtualMailboxListParams as VirtualMailboxListParams from .bank_account_delete_response import BankAccountDeleteResponse as BankAccountDeleteResponse @@ -98,6 +100,7 @@ from .mailing_list_delete_response import MailingListDeleteResponse as MailingListDeleteResponse from .mailing_list_import_response import MailingListImportResponse as MailingListImportResponse from .sub_organization_list_params import SubOrganizationListParams as SubOrganizationListParams +from .return_envelope_create_params import ReturnEnvelopeCreateParams as ReturnEnvelopeCreateParams from .virtual_mailbox_create_params import VirtualMailboxCreateParams as VirtualMailboxCreateParams from .virtual_mailbox_list_response import VirtualMailboxListResponse as VirtualMailboxListResponse from .postcard_retrieve_url_response import PostcardRetrieveURLResponse as PostcardRetrieveURLResponse diff --git a/src/postgrid/types/print_mail/cheque.py b/src/postgrid/types/print_mail/cheque.py index cc68ef9..4210c6e 100644 --- a/src/postgrid/types/print_mail/cheque.py +++ b/src/postgrid/types/print_mail/cheque.py @@ -168,7 +168,23 @@ class Cheque(BaseModel): through. Only populated when an `imbStatus` is present. """ - logo_url: Optional[str] = FieldInfo(alias="logoURL", default=None) + letter_html: Optional[str] = FieldInfo(alias="letterHTML", default=None) + """The raw HTML content for a letter attached to the cheque, if any. + + You can supply _either_ this, `letterTemplate`, or `letterPDF`, but not more + than one. + """ + + letter_template: Optional[str] = FieldInfo(alias="letterTemplate", default=None) + """A Template ID for the letter attached to the cheque, if any.""" + + letter_uploaded_pdf: Optional[str] = FieldInfo(alias="letterUploadedPDF", default=None) + """ + A signed URL pointing to the original PDF of the letter attached to the cheque, + if any. + """ + + logo: Optional[str] = None """An optional logo URL for the cheque. This will be placed next to the recipient address at the top left corner of the @@ -201,6 +217,12 @@ class Cheque(BaseModel): has a unique number. """ + return_envelope: Optional[str] = FieldInfo(alias="returnEnvelope", default=None) + """The return envelope (ID) sent out with the cheque, if any. + + Note that you must first order return envelopes using the Return Envelopes API. + """ + tracking_number: Optional[str] = FieldInfo(alias="trackingNumber", default=None) """The tracking number of this order. diff --git a/src/postgrid/types/print_mail/cheque_create_params.py b/src/postgrid/types/print_mail/cheque_create_params.py index 365311c..d7cb6d8 100644 --- a/src/postgrid/types/print_mail/cheque_create_params.py +++ b/src/postgrid/types/print_mail/cheque_create_params.py @@ -6,13 +6,14 @@ from datetime import datetime from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from ..._types import Base64FileInput from ..._utils import PropertyInfo from .cheque_size import ChequeSize from .digital_only_param import DigitalOnlyParam from .contact_create_with_first_name_param import ContactCreateWithFirstNameParam from .contact_create_with_company_name_param import ContactCreateWithCompanyNameParam -__all__ = ["ChequeCreateParams", "From", "To", "RedirectTo"] +__all__ = ["ChequeCreateParams", "From", "To", "LetterSettings", "RedirectTo"] class ChequeCreateParams(TypedDict, total=False): @@ -63,7 +64,27 @@ class ChequeCreateParams(TypedDict, total=False): If a custom envelope ID is not specified, defaults to `standard`. """ - logo_url: Annotated[str, PropertyInfo(alias="logoURL")] + letter_html: Annotated[str, PropertyInfo(alias="letterHTML")] + """The raw HTML content for a letter attached to the cheque, if any. + + You can supply _either_ this, `letterTemplate`, or `letterPDF`, but not more + than one. + """ + + letter_pdf: Annotated[Union[str, Base64FileInput], PropertyInfo(alias="letterPDF", format="base64")] + """ + A URL pointing to a PDF for the letter attached to the cheque, or the PDF file + itself when uploaded via a multipart form request. You can supply _either_ this, + `letterHTML`, or `letterTemplate`, but not more than one. + """ + + letter_settings: Annotated[LetterSettings, PropertyInfo(alias="letterSettings")] + """Settings for a letter attached to a cheque.""" + + letter_template: Annotated[str, PropertyInfo(alias="letterTemplate")] + """A Template ID for the letter attached to the cheque, if any.""" + + logo: str """An optional logo URL for the cheque. This will be placed next to the recipient address at the top left corner of the @@ -141,6 +162,12 @@ class ChequeCreateParams(TypedDict, total=False): signing cheques at your office before mailing them out yourself. """ + return_envelope: Annotated[str, PropertyInfo(alias="returnEnvelope")] + """The return envelope (ID) sent out with the cheque, if any. + + Note that you must first order return envelopes using the Return Envelopes API. + """ + send_date: Annotated[Union[str, datetime], PropertyInfo(alias="sendDate", format="iso8601")] """This order will transition from `ready` to `printing` on the day after this date. @@ -156,4 +183,15 @@ class ChequeCreateParams(TypedDict, total=False): To: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] + +class LetterSettings(TypedDict, total=False): + """Settings for a letter attached to a cheque.""" + + placement: Literal["before_cheque", "after_cheque"] + """ + Enum representing where a letter attached to a cheque is placed relative to the + cheque page. + """ + + RedirectTo: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] diff --git a/src/postgrid/types/print_mail/contact.py b/src/postgrid/types/print_mail/contact.py index aa21c16..c6f420f 100644 --- a/src/postgrid/types/print_mail/contact.py +++ b/src/postgrid/types/print_mail/contact.py @@ -88,6 +88,13 @@ class Contact(BaseModel): province_or_state: Optional[str] = FieldInfo(alias="provinceOrState", default=None) """Province or state of the contact's address.""" + secret: Optional[bool] = None + """ + If `true`, the contact's details are hidden from the dashboard and API responses + apart from the final print. The contact ID can then be used as a token for + sending mail without giving access to the underlying data. + """ + skip_verification: Optional[bool] = FieldInfo(alias="skipVerification", default=None) """ If `true`, PostGrid will skip running this contact's address through our address diff --git a/src/postgrid/types/print_mail/contact_create_params.py b/src/postgrid/types/print_mail/contact_create_params.py index 19a56f1..0967e58 100644 --- a/src/postgrid/types/print_mail/contact_create_params.py +++ b/src/postgrid/types/print_mail/contact_create_params.py @@ -61,6 +61,13 @@ class ContactCreateWithFirstName(TypedDict, total=False): province_or_state: Annotated[str, PropertyInfo(alias="provinceOrState")] """Province or state of the contact's address.""" + secret: bool + """ + If `true`, the contact's details are hidden from the dashboard and API responses + apart from the final print. The contact ID can then be used as a token for + sending mail without giving access to the underlying data. + """ + skip_verification: Annotated[bool, PropertyInfo(alias="skipVerification")] """ If `true`, PostGrid will skip running this contact's address through our address @@ -119,6 +126,13 @@ class ContactCreateWithCompanyName(TypedDict, total=False): province_or_state: Annotated[str, PropertyInfo(alias="provinceOrState")] """Province or state of the contact's address.""" + secret: bool + """ + If `true`, the contact's details are hidden from the dashboard and API responses + apart from the final print. The contact ID can then be used as a token for + sending mail without giving access to the underlying data. + """ + skip_verification: Annotated[bool, PropertyInfo(alias="skipVerification")] """ If `true`, PostGrid will skip running this contact's address through our address diff --git a/src/postgrid/types/print_mail/contact_create_with_company_name_param.py b/src/postgrid/types/print_mail/contact_create_with_company_name_param.py index e3ba4f1..303860c 100644 --- a/src/postgrid/types/print_mail/contact_create_with_company_name_param.py +++ b/src/postgrid/types/print_mail/contact_create_with_company_name_param.py @@ -61,6 +61,13 @@ class ContactCreateWithCompanyNameParam(TypedDict, total=False): province_or_state: Annotated[str, PropertyInfo(alias="provinceOrState")] """Province or state of the contact's address.""" + secret: bool + """ + If `true`, the contact's details are hidden from the dashboard and API responses + apart from the final print. The contact ID can then be used as a token for + sending mail without giving access to the underlying data. + """ + skip_verification: Annotated[bool, PropertyInfo(alias="skipVerification")] """ If `true`, PostGrid will skip running this contact's address through our address diff --git a/src/postgrid/types/print_mail/contact_create_with_first_name_param.py b/src/postgrid/types/print_mail/contact_create_with_first_name_param.py index b4e0da9..c1b6c65 100644 --- a/src/postgrid/types/print_mail/contact_create_with_first_name_param.py +++ b/src/postgrid/types/print_mail/contact_create_with_first_name_param.py @@ -61,6 +61,13 @@ class ContactCreateWithFirstNameParam(TypedDict, total=False): province_or_state: Annotated[str, PropertyInfo(alias="provinceOrState")] """Province or state of the contact's address.""" + secret: bool + """ + If `true`, the contact's details are hidden from the dashboard and API responses + apart from the final print. The contact ID can then be used as a token for + sending mail without giving access to the underlying data. + """ + skip_verification: Annotated[bool, PropertyInfo(alias="skipVerification")] """ If `true`, PostGrid will skip running this contact's address through our address diff --git a/src/postgrid/types/print_mail/digital_only.py b/src/postgrid/types/print_mail/digital_only.py index 8d3e693..3f667e7 100644 --- a/src/postgrid/types/print_mail/digital_only.py +++ b/src/postgrid/types/print_mail/digital_only.py @@ -1,10 +1,31 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from typing import Optional + from ..._models import BaseModel -__all__ = ["DigitalOnly"] +__all__ = ["DigitalOnly", "Payee"] + + +class Payee(BaseModel): + """The payee of the digital cheque. + + Supplying `payee.name` lets you create a + digital-only cheque without a `to` contact — when it is provided, the + top-level `to` field may be omitted. + """ + + name: str + """The name of the payee.""" class DigitalOnly(BaseModel): watermark: str """Text to be displayed as a watermark on the digital cheque.""" + + payee: Optional[Payee] = None + """The payee of the digital cheque. + + Supplying `payee.name` lets you create a digital-only cheque without a `to` + contact — when it is provided, the top-level `to` field may be omitted. + """ diff --git a/src/postgrid/types/print_mail/digital_only_param.py b/src/postgrid/types/print_mail/digital_only_param.py index 2637e5a..71c1762 100644 --- a/src/postgrid/types/print_mail/digital_only_param.py +++ b/src/postgrid/types/print_mail/digital_only_param.py @@ -4,9 +4,28 @@ from typing_extensions import Required, TypedDict -__all__ = ["DigitalOnlyParam"] +__all__ = ["DigitalOnlyParam", "Payee"] + + +class Payee(TypedDict, total=False): + """The payee of the digital cheque. + + Supplying `payee.name` lets you create a + digital-only cheque without a `to` contact — when it is provided, the + top-level `to` field may be omitted. + """ + + name: Required[str] + """The name of the payee.""" class DigitalOnlyParam(TypedDict, total=False): watermark: Required[str] """Text to be displayed as a watermark on the digital cheque.""" + + payee: Payee + """The payee of the digital cheque. + + Supplying `payee.name` lets you create a digital-only cheque without a `to` + contact — when it is provided, the top-level `to` field may be omitted. + """ diff --git a/src/postgrid/types/print_mail/return_envelope.py b/src/postgrid/types/print_mail/return_envelope.py new file mode 100644 index 0000000..2726087 --- /dev/null +++ b/src/postgrid/types/print_mail/return_envelope.py @@ -0,0 +1,137 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import builtins +from typing import Dict, Optional +from datetime import datetime +from typing_extensions import Literal + +from pydantic import Field as FieldInfo + +from ..._models import BaseModel + +__all__ = ["ReturnEnvelope", "To"] + + +class To(BaseModel): + """The contact denormalized onto a return envelope when it is created. + + Unlike + a full contact it is not a standalone resource, so it has no `object`, + `live`, `createdAt`, or `updatedAt` fields. + """ + + id: str + """A unique ID prefixed with contact\\__""" + + address_line1: str = FieldInfo(alias="addressLine1") + """The first line of the contact's address.""" + + address_status: Literal["verified", "corrected", "failed"] = FieldInfo(alias="addressStatus") + """One of `verified`, `corrected`, or `failed`.""" + + country_code: str = FieldInfo(alias="countryCode") + """The ISO 3611-1 country code of the contact's address.""" + + address_errors: Optional[str] = FieldInfo(alias="addressErrors", default=None) + """ + A series of human-readable errors/warnings that were raised when running the + provided address through our address verification. + """ + + address_line2: Optional[str] = FieldInfo(alias="addressLine2", default=None) + """Second line of the contact's address, if applicable.""" + + city: Optional[str] = None + """The city of the contact's address.""" + + company_name: Optional[str] = FieldInfo(alias="companyName", default=None) + """Company name of the contact.""" + + description: Optional[str] = None + """An optional string describing this resource. + + Will be visible in the API and the dashboard. + """ + + email: Optional[str] = None + """Email of the contact.""" + + first_name: Optional[str] = FieldInfo(alias="firstName", default=None) + """First name of the contact.""" + + force_verified_status: Optional[bool] = FieldInfo(alias="forceVerifiedStatus", default=None) + """ + If `true`, PostGrid will force this contact to have an `addressStatus` of + `verified` even if our address verification system says otherwise. + """ + + job_title: Optional[str] = FieldInfo(alias="jobTitle", default=None) + """Job title of the contact.""" + + last_name: Optional[str] = FieldInfo(alias="lastName", default=None) + """Last name of the contact.""" + + metadata: Optional[Dict[str, object]] = None + """See the section on Metadata.""" + + phone_number: Optional[str] = FieldInfo(alias="phoneNumber", default=None) + """Phone number of the contact.""" + + postal_or_zip: Optional[str] = FieldInfo(alias="postalOrZip", default=None) + """The postal or ZIP code of the contact's address.""" + + province_or_state: Optional[str] = FieldInfo(alias="provinceOrState", default=None) + """Province or state of the contact's address.""" + + secret: Optional[bool] = None + """ + If `true`, the contact's details are hidden from the dashboard and API responses + apart from the final print. The contact ID can then be used as a token for + sending mail without giving access to the underlying data. + """ + + skip_verification: Optional[bool] = FieldInfo(alias="skipVerification", default=None) + """ + If `true`, PostGrid will skip running this contact's address through our address + verification system. + """ + + +class ReturnEnvelope(BaseModel): + id: str + """A unique ID prefixed with return*envelope*""" + + available: int + """The number of return envelopes available to use in your orders immediately. + + This increases when a return envelope order is filled and decreases as you send + orders which include this return envelope. + """ + + created_at: datetime = FieldInfo(alias="createdAt") + """The UTC time at which this resource was created.""" + + live: bool + """`true` if this is a live mode resource else `false`.""" + + object: Literal["return_envelope"] + """Always `return_envelope`.""" + + to: To + """The contact denormalized onto a return envelope when it is created. + + Unlike a full contact it is not a standalone resource, so it has no `object`, + `live`, `createdAt`, or `updatedAt` fields. + """ + + updated_at: datetime = FieldInfo(alias="updatedAt") + """The UTC time at which this resource was last updated.""" + + description: Optional[str] = None + """An optional string describing this resource. + + Will be visible in the API and the dashboard. + """ + + metadata: Optional[Dict[str, builtins.object]] = None + """See the section on Metadata.""" diff --git a/src/postgrid/types/print_mail/return_envelope_create_params.py b/src/postgrid/types/print_mail/return_envelope_create_params.py new file mode 100644 index 0000000..43772fc --- /dev/null +++ b/src/postgrid/types/print_mail/return_envelope_create_params.py @@ -0,0 +1,34 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict, Union +from typing_extensions import Required, Annotated, TypeAlias, TypedDict + +from ..._utils import PropertyInfo +from .contact_create_with_first_name_param import ContactCreateWithFirstNameParam +from .contact_create_with_company_name_param import ContactCreateWithCompanyNameParam + +__all__ = ["ReturnEnvelopeCreateParams", "To"] + + +class ReturnEnvelopeCreateParams(TypedDict, total=False): + to: Required[To] + """ + A contact ID or a contact object containing the address that will be printed + onto the return envelope. + """ + + description: str + """An optional string describing this resource. + + Will be visible in the API and the dashboard. + """ + + metadata: Dict[str, object] + """See the section on Metadata.""" + + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + + +To: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] diff --git a/src/postgrid/types/print_mail/return_envelope_list_params.py b/src/postgrid/types/print_mail/return_envelope_list_params.py new file mode 100644 index 0000000..7b631cc --- /dev/null +++ b/src/postgrid/types/print_mail/return_envelope_list_params.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["ReturnEnvelopeListParams"] + + +class ReturnEnvelopeListParams(TypedDict, total=False): + limit: int + + search: str + """You can supply any string to help narrow down the list of resources. + + For example, if you pass `"New York"` (quoted), it will return resources that + have that string present somewhere in their response. Alternatively, you can + supply a structured search query. See the documentation on + `StructuredSearchQuery` for more details. + """ + + skip: int diff --git a/src/postgrid/types/print_mail/return_envelopes/__init__.py b/src/postgrid/types/print_mail/return_envelopes/__init__.py new file mode 100644 index 0000000..5058218 --- /dev/null +++ b/src/postgrid/types/print_mail/return_envelopes/__init__.py @@ -0,0 +1,9 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from .order_list_params import OrderListParams as OrderListParams +from .order_cancel_params import OrderCancelParams as OrderCancelParams +from .order_create_params import OrderCreateParams as OrderCreateParams +from .order_retrieve_params import OrderRetrieveParams as OrderRetrieveParams +from .return_envelope_order import ReturnEnvelopeOrder as ReturnEnvelopeOrder diff --git a/src/postgrid/types/print_mail/return_envelopes/order_cancel_params.py b/src/postgrid/types/print_mail/return_envelopes/order_cancel_params.py new file mode 100644 index 0000000..55cc152 --- /dev/null +++ b/src/postgrid/types/print_mail/return_envelopes/order_cancel_params.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["OrderCancelParams"] + + +class OrderCancelParams(TypedDict, total=False): + id: Required[str] + + expand: List[Literal["returnEnvelope"]] + """ + Pass `expand[]=returnEnvelope` to expand the order's `returnEnvelope` field into + the full return envelope object. + """ diff --git a/src/postgrid/types/print_mail/return_envelopes/order_create_params.py b/src/postgrid/types/print_mail/return_envelopes/order_create_params.py new file mode 100644 index 0000000..9f297e9 --- /dev/null +++ b/src/postgrid/types/print_mail/return_envelopes/order_create_params.py @@ -0,0 +1,24 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import Dict +from typing_extensions import Required, Annotated, TypedDict + +from ...._utils import PropertyInfo + +__all__ = ["OrderCreateParams"] + + +class OrderCreateParams(TypedDict, total=False): + quantity_ordered: Required[Annotated[int, PropertyInfo(alias="quantityOrdered")]] + """The quantity of return envelopes ordered. Minimum 5000.""" + + description: str + """An optional string describing this resource. + + Will be visible in the API and the dashboard. + """ + + metadata: Dict[str, object] + """See the section on Metadata.""" diff --git a/src/postgrid/types/print_mail/return_envelopes/order_list_params.py b/src/postgrid/types/print_mail/return_envelopes/order_list_params.py new file mode 100644 index 0000000..83c4cc4 --- /dev/null +++ b/src/postgrid/types/print_mail/return_envelopes/order_list_params.py @@ -0,0 +1,22 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing_extensions import TypedDict + +__all__ = ["OrderListParams"] + + +class OrderListParams(TypedDict, total=False): + limit: int + + search: str + """You can supply any string to help narrow down the list of resources. + + For example, if you pass `"New York"` (quoted), it will return resources that + have that string present somewhere in their response. Alternatively, you can + supply a structured search query. See the documentation on + `StructuredSearchQuery` for more details. + """ + + skip: int diff --git a/src/postgrid/types/print_mail/return_envelopes/order_retrieve_params.py b/src/postgrid/types/print_mail/return_envelopes/order_retrieve_params.py new file mode 100644 index 0000000..6ea7694 --- /dev/null +++ b/src/postgrid/types/print_mail/return_envelopes/order_retrieve_params.py @@ -0,0 +1,18 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +from typing import List +from typing_extensions import Literal, Required, TypedDict + +__all__ = ["OrderRetrieveParams"] + + +class OrderRetrieveParams(TypedDict, total=False): + id: Required[str] + + expand: List[Literal["returnEnvelope"]] + """ + Pass `expand[]=returnEnvelope` to expand the order's `returnEnvelope` field into + the full return envelope object. + """ diff --git a/src/postgrid/types/print_mail/return_envelopes/return_envelope_order.py b/src/postgrid/types/print_mail/return_envelopes/return_envelope_order.py new file mode 100644 index 0000000..c2f97b7 --- /dev/null +++ b/src/postgrid/types/print_mail/return_envelopes/return_envelope_order.py @@ -0,0 +1,60 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import builtins +from typing import Dict, Union, Optional +from datetime import datetime +from typing_extensions import Literal, TypeAlias + +from pydantic import Field as FieldInfo + +from .. import return_envelope +from ...._models import BaseModel + +__all__ = ["ReturnEnvelopeOrder", "ReturnEnvelope"] + +ReturnEnvelope: TypeAlias = Union[str, return_envelope.ReturnEnvelope] + + +class ReturnEnvelopeOrder(BaseModel): + id: str + """A unique ID prefixed with return*envelope_order*""" + + created_at: datetime = FieldInfo(alias="createdAt") + """The UTC time at which this resource was created.""" + + live: bool + """`true` if this is a live mode resource else `false`.""" + + object: Literal["return_envelope_order"] + """Always `return_envelope_order`.""" + + quantity_ordered: int = FieldInfo(alias="quantityOrdered") + """The quantity of return envelopes ordered. Minimum 5000.""" + + return_envelope: ReturnEnvelope = FieldInfo(alias="returnEnvelope") + """The ID of the return envelope that this order replenishes. + + Expanded into the full return envelope object on the individual order retrieval + and cancellation endpoints when `expand[]=returnEnvelope` is supplied. + """ + + status: Literal["placed", "filled", "cancelled"] + """The status of a return envelope order.""" + + updated_at: datetime = FieldInfo(alias="updatedAt") + """The UTC time at which this resource was last updated.""" + + description: Optional[str] = None + """An optional string describing this resource. + + Will be visible in the API and the dashboard. + """ + + metadata: Optional[Dict[str, builtins.object]] = None + """See the section on Metadata.""" + + quantity_filled: Optional[int] = FieldInfo(alias="quantityFilled", default=None) + """The quantity of return envelopes that were filled for this order. + + Only returned once the order's status is `filled`. + """ diff --git a/tests/api_resources/print_mail/return_envelopes/__init__.py b/tests/api_resources/print_mail/return_envelopes/__init__.py new file mode 100644 index 0000000..fd8019a --- /dev/null +++ b/tests/api_resources/print_mail/return_envelopes/__init__.py @@ -0,0 +1 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. diff --git a/tests/api_resources/print_mail/return_envelopes/test_orders.py b/tests/api_resources/print_mail/return_envelopes/test_orders.py new file mode 100644 index 0000000..a014209 --- /dev/null +++ b/tests/api_resources/print_mail/return_envelopes/test_orders.py @@ -0,0 +1,599 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from postgrid import PostGrid, AsyncPostGrid +from tests.utils import assert_matches_type +from postgrid.pagination import SyncSkipLimit, AsyncSkipLimit +from postgrid.types.print_mail.return_envelopes import ( + ReturnEnvelopeOrder, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestOrders: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create(self, client: PostGrid) -> None: + order = client.print_mail.return_envelopes.orders.create( + id="id", + quantity_ordered=5000, + ) + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: PostGrid) -> None: + order = client.print_mail.return_envelopes.orders.create( + id="id", + quantity_ordered=5000, + description="A batch of 5000", + metadata={"foo": "bar"}, + ) + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_create(self, client: PostGrid) -> None: + response = client.print_mail.return_envelopes.orders.with_raw_response.create( + id="id", + quantity_ordered=5000, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + order = response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_create(self, client: PostGrid) -> None: + with client.print_mail.return_envelopes.orders.with_streaming_response.create( + id="id", + quantity_ordered=5000, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + order = response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_create(self, client: PostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.print_mail.return_envelopes.orders.with_raw_response.create( + id="", + quantity_ordered=5000, + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve(self, client: PostGrid) -> None: + order = client.print_mail.return_envelopes.orders.retrieve( + order_id="orderID", + id="id", + ) + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve_with_all_params(self, client: PostGrid) -> None: + order = client.print_mail.return_envelopes.orders.retrieve( + order_id="orderID", + id="id", + expand=["returnEnvelope"], + ) + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: PostGrid) -> None: + response = client.print_mail.return_envelopes.orders.with_raw_response.retrieve( + order_id="orderID", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + order = response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: PostGrid) -> None: + with client.print_mail.return_envelopes.orders.with_streaming_response.retrieve( + order_id="orderID", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + order = response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: PostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.print_mail.return_envelopes.orders.with_raw_response.retrieve( + order_id="orderID", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `order_id` but received ''"): + client.print_mail.return_envelopes.orders.with_raw_response.retrieve( + order_id="", + id="id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: PostGrid) -> None: + order = client.print_mail.return_envelopes.orders.list( + id="id", + ) + assert_matches_type(SyncSkipLimit[ReturnEnvelopeOrder], order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: PostGrid) -> None: + order = client.print_mail.return_envelopes.orders.list( + id="id", + limit=0, + search="search", + skip=0, + ) + assert_matches_type(SyncSkipLimit[ReturnEnvelopeOrder], order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: PostGrid) -> None: + response = client.print_mail.return_envelopes.orders.with_raw_response.list( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + order = response.parse() + assert_matches_type(SyncSkipLimit[ReturnEnvelopeOrder], order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: PostGrid) -> None: + with client.print_mail.return_envelopes.orders.with_streaming_response.list( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + order = response.parse() + assert_matches_type(SyncSkipLimit[ReturnEnvelopeOrder], order, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_list(self, client: PostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.print_mail.return_envelopes.orders.with_raw_response.list( + id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_cancel(self, client: PostGrid) -> None: + order = client.print_mail.return_envelopes.orders.cancel( + order_id="orderID", + id="id", + ) + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_cancel_with_all_params(self, client: PostGrid) -> None: + order = client.print_mail.return_envelopes.orders.cancel( + order_id="orderID", + id="id", + expand=["returnEnvelope"], + ) + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_cancel(self, client: PostGrid) -> None: + response = client.print_mail.return_envelopes.orders.with_raw_response.cancel( + order_id="orderID", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + order = response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_cancel(self, client: PostGrid) -> None: + with client.print_mail.return_envelopes.orders.with_streaming_response.cancel( + order_id="orderID", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + order = response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_cancel(self, client: PostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.print_mail.return_envelopes.orders.with_raw_response.cancel( + order_id="orderID", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `order_id` but received ''"): + client.print_mail.return_envelopes.orders.with_raw_response.cancel( + order_id="", + id="id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_fill(self, client: PostGrid) -> None: + order = client.print_mail.return_envelopes.orders.fill( + order_id="orderID", + id="id", + ) + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_fill(self, client: PostGrid) -> None: + response = client.print_mail.return_envelopes.orders.with_raw_response.fill( + order_id="orderID", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + order = response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_fill(self, client: PostGrid) -> None: + with client.print_mail.return_envelopes.orders.with_streaming_response.fill( + order_id="orderID", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + order = response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_fill(self, client: PostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.print_mail.return_envelopes.orders.with_raw_response.fill( + order_id="orderID", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `order_id` but received ''"): + client.print_mail.return_envelopes.orders.with_raw_response.fill( + order_id="", + id="id", + ) + + +class TestAsyncOrders: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncPostGrid) -> None: + order = await async_client.print_mail.return_envelopes.orders.create( + id="id", + quantity_ordered=5000, + ) + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncPostGrid) -> None: + order = await async_client.print_mail.return_envelopes.orders.create( + id="id", + quantity_ordered=5000, + description="A batch of 5000", + metadata={"foo": "bar"}, + ) + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.return_envelopes.orders.with_raw_response.create( + id="id", + quantity_ordered=5000, + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + order = await response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.return_envelopes.orders.with_streaming_response.create( + id="id", + quantity_ordered=5000, + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + order = await response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_create(self, async_client: AsyncPostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.print_mail.return_envelopes.orders.with_raw_response.create( + id="", + quantity_ordered=5000, + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncPostGrid) -> None: + order = await async_client.print_mail.return_envelopes.orders.retrieve( + order_id="orderID", + id="id", + ) + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve_with_all_params(self, async_client: AsyncPostGrid) -> None: + order = await async_client.print_mail.return_envelopes.orders.retrieve( + order_id="orderID", + id="id", + expand=["returnEnvelope"], + ) + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.return_envelopes.orders.with_raw_response.retrieve( + order_id="orderID", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + order = await response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.return_envelopes.orders.with_streaming_response.retrieve( + order_id="orderID", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + order = await response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncPostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.print_mail.return_envelopes.orders.with_raw_response.retrieve( + order_id="orderID", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `order_id` but received ''"): + await async_client.print_mail.return_envelopes.orders.with_raw_response.retrieve( + order_id="", + id="id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncPostGrid) -> None: + order = await async_client.print_mail.return_envelopes.orders.list( + id="id", + ) + assert_matches_type(AsyncSkipLimit[ReturnEnvelopeOrder], order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncPostGrid) -> None: + order = await async_client.print_mail.return_envelopes.orders.list( + id="id", + limit=0, + search="search", + skip=0, + ) + assert_matches_type(AsyncSkipLimit[ReturnEnvelopeOrder], order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.return_envelopes.orders.with_raw_response.list( + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + order = await response.parse() + assert_matches_type(AsyncSkipLimit[ReturnEnvelopeOrder], order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.return_envelopes.orders.with_streaming_response.list( + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + order = await response.parse() + assert_matches_type(AsyncSkipLimit[ReturnEnvelopeOrder], order, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_list(self, async_client: AsyncPostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.print_mail.return_envelopes.orders.with_raw_response.list( + id="", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_cancel(self, async_client: AsyncPostGrid) -> None: + order = await async_client.print_mail.return_envelopes.orders.cancel( + order_id="orderID", + id="id", + ) + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_cancel_with_all_params(self, async_client: AsyncPostGrid) -> None: + order = await async_client.print_mail.return_envelopes.orders.cancel( + order_id="orderID", + id="id", + expand=["returnEnvelope"], + ) + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_cancel(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.return_envelopes.orders.with_raw_response.cancel( + order_id="orderID", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + order = await response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_cancel(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.return_envelopes.orders.with_streaming_response.cancel( + order_id="orderID", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + order = await response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_cancel(self, async_client: AsyncPostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.print_mail.return_envelopes.orders.with_raw_response.cancel( + order_id="orderID", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `order_id` but received ''"): + await async_client.print_mail.return_envelopes.orders.with_raw_response.cancel( + order_id="", + id="id", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_fill(self, async_client: AsyncPostGrid) -> None: + order = await async_client.print_mail.return_envelopes.orders.fill( + order_id="orderID", + id="id", + ) + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_fill(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.return_envelopes.orders.with_raw_response.fill( + order_id="orderID", + id="id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + order = await response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_fill(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.return_envelopes.orders.with_streaming_response.fill( + order_id="orderID", + id="id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + order = await response.parse() + assert_matches_type(ReturnEnvelopeOrder, order, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_fill(self, async_client: AsyncPostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.print_mail.return_envelopes.orders.with_raw_response.fill( + order_id="orderID", + id="", + ) + + with pytest.raises(ValueError, match=r"Expected a non-empty value for `order_id` but received ''"): + await async_client.print_mail.return_envelopes.orders.with_raw_response.fill( + order_id="", + id="id", + ) diff --git a/tests/api_resources/print_mail/test_cheques.py b/tests/api_resources/print_mail/test_cheques.py index a981f5e..dd9f113 100644 --- a/tests/api_resources/print_mail/test_cheques.py +++ b/tests/api_resources/print_mail/test_cheques.py @@ -43,9 +43,16 @@ def test_method_create_with_all_params(self, client: PostGrid) -> None: to="contact_123", currency_code="USD", description="description", - digital_only={"watermark": "watermark"}, + digital_only={ + "watermark": "watermark", + "payee": {"name": "name"}, + }, envelope="standard", - logo_url="https://example.com", + letter_html="letterHTML", + letter_pdf="U3RhaW5sZXNzIHJvY2tz", + letter_settings={"placement": "before_cheque"}, + letter_template="letterTemplate", + logo="https://example.com", mailing_class="first_class", memo="memo", merge_variables={"foo": "bar"}, @@ -68,8 +75,10 @@ def test_method_create_with_all_params(self, client: PostGrid) -> None: "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, + return_envelope="returnEnvelope", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), size="us_letter", ) @@ -428,9 +437,16 @@ async def test_method_create_with_all_params(self, async_client: AsyncPostGrid) to="contact_123", currency_code="USD", description="description", - digital_only={"watermark": "watermark"}, + digital_only={ + "watermark": "watermark", + "payee": {"name": "name"}, + }, envelope="standard", - logo_url="https://example.com", + letter_html="letterHTML", + letter_pdf="U3RhaW5sZXNzIHJvY2tz", + letter_settings={"placement": "before_cheque"}, + letter_template="letterTemplate", + logo="https://example.com", mailing_class="first_class", memo="memo", merge_variables={"foo": "bar"}, @@ -453,8 +469,10 @@ async def test_method_create_with_all_params(self, async_client: AsyncPostGrid) "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, + return_envelope="returnEnvelope", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), size="us_letter", ) diff --git a/tests/api_resources/print_mail/test_contacts.py b/tests/api_resources/print_mail/test_contacts.py index df470a5..5f2bc72 100644 --- a/tests/api_resources/print_mail/test_contacts.py +++ b/tests/api_resources/print_mail/test_contacts.py @@ -47,6 +47,7 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non phone_number="phoneNumber", postal_or_zip="postalOrZip", province_or_state="provinceOrState", + secret=True, skip_verification=True, ) assert_matches_type(Contact, contact, path=["response"]) @@ -110,6 +111,7 @@ def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> Non phone_number="phoneNumber", postal_or_zip="postalOrZip", province_or_state="provinceOrState", + secret=True, skip_verification=True, ) assert_matches_type(Contact, contact, path=["response"]) @@ -301,6 +303,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn phone_number="phoneNumber", postal_or_zip="postalOrZip", province_or_state="provinceOrState", + secret=True, skip_verification=True, ) assert_matches_type(Contact, contact, path=["response"]) @@ -364,6 +367,7 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn phone_number="phoneNumber", postal_or_zip="postalOrZip", province_or_state="provinceOrState", + secret=True, skip_verification=True, ) assert_matches_type(Contact, contact, path=["response"]) diff --git a/tests/api_resources/print_mail/test_letters.py b/tests/api_resources/print_mail/test_letters.py index c342b7f..cdbb8b5 100644 --- a/tests/api_resources/print_mail/test_letters.py +++ b/tests/api_resources/print_mail/test_letters.py @@ -60,6 +60,7 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, html="html", @@ -79,6 +80,7 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, address_placement="top_first_page", @@ -200,6 +202,7 @@ def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, template="template", @@ -219,6 +222,7 @@ def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, address_placement="top_first_page", @@ -340,6 +344,7 @@ def test_method_create_with_all_params_overload_3(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, pdf="https://example.com", @@ -359,6 +364,7 @@ def test_method_create_with_all_params_overload_3(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, address_placement="top_first_page", @@ -738,6 +744,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, html="html", @@ -757,6 +764,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, address_placement="top_first_page", @@ -878,6 +886,7 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, template="template", @@ -897,6 +906,7 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, address_placement="top_first_page", @@ -1018,6 +1028,7 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, pdf="https://example.com", @@ -1037,6 +1048,7 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, address_placement="top_first_page", diff --git a/tests/api_resources/print_mail/test_postcards.py b/tests/api_resources/print_mail/test_postcards.py index 9a177bb..8f2fb46 100644 --- a/tests/api_resources/print_mail/test_postcards.py +++ b/tests/api_resources/print_mail/test_postcards.py @@ -60,6 +60,7 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -79,6 +80,7 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, mailing_class="first_class", @@ -167,6 +169,7 @@ def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -186,6 +189,7 @@ def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, mailing_class="first_class", @@ -272,6 +276,7 @@ def test_method_create_with_all_params_overload_3(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -291,6 +296,7 @@ def test_method_create_with_all_params_overload_3(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, mailing_class="first_class", @@ -375,6 +381,7 @@ def test_method_create_with_all_params_overload_4(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -394,6 +401,7 @@ def test_method_create_with_all_params_overload_4(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, mailing_class="first_class", @@ -738,6 +746,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -757,6 +766,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, mailing_class="first_class", @@ -845,6 +855,7 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -864,6 +875,7 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, mailing_class="first_class", @@ -950,6 +962,7 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -969,6 +982,7 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, mailing_class="first_class", @@ -1053,6 +1067,7 @@ async def test_method_create_with_all_params_overload_4(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -1072,6 +1087,7 @@ async def test_method_create_with_all_params_overload_4(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, mailing_class="first_class", diff --git a/tests/api_resources/print_mail/test_return_envelopes.py b/tests/api_resources/print_mail/test_return_envelopes.py new file mode 100644 index 0000000..1daa09a --- /dev/null +++ b/tests/api_resources/print_mail/test_return_envelopes.py @@ -0,0 +1,275 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from postgrid import PostGrid, AsyncPostGrid +from tests.utils import assert_matches_type +from postgrid.pagination import SyncSkipLimit, AsyncSkipLimit +from postgrid.types.print_mail import ReturnEnvelope + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestReturnEnvelopes: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create(self, client: PostGrid) -> None: + return_envelope = client.print_mail.return_envelopes.create( + to="contact_kFjQtFqJtRXgahx5vgc9mA", + ) + assert_matches_type(ReturnEnvelope, return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_create_with_all_params(self, client: PostGrid) -> None: + return_envelope = client.print_mail.return_envelopes.create( + to="contact_kFjQtFqJtRXgahx5vgc9mA", + description="description", + metadata={"foo": "bar"}, + idempotency_key="idempotency-key", + ) + assert_matches_type(ReturnEnvelope, return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_create(self, client: PostGrid) -> None: + response = client.print_mail.return_envelopes.with_raw_response.create( + to="contact_kFjQtFqJtRXgahx5vgc9mA", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + return_envelope = response.parse() + assert_matches_type(ReturnEnvelope, return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_create(self, client: PostGrid) -> None: + with client.print_mail.return_envelopes.with_streaming_response.create( + to="contact_kFjQtFqJtRXgahx5vgc9mA", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + return_envelope = response.parse() + assert_matches_type(ReturnEnvelope, return_envelope, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve(self, client: PostGrid) -> None: + return_envelope = client.print_mail.return_envelopes.retrieve( + "id", + ) + assert_matches_type(ReturnEnvelope, return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: PostGrid) -> None: + response = client.print_mail.return_envelopes.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + return_envelope = response.parse() + assert_matches_type(ReturnEnvelope, return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: PostGrid) -> None: + with client.print_mail.return_envelopes.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + return_envelope = response.parse() + assert_matches_type(ReturnEnvelope, return_envelope, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: PostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.print_mail.return_envelopes.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: PostGrid) -> None: + return_envelope = client.print_mail.return_envelopes.list() + assert_matches_type(SyncSkipLimit[ReturnEnvelope], return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: PostGrid) -> None: + return_envelope = client.print_mail.return_envelopes.list( + limit=0, + search="search", + skip=0, + ) + assert_matches_type(SyncSkipLimit[ReturnEnvelope], return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: PostGrid) -> None: + response = client.print_mail.return_envelopes.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + return_envelope = response.parse() + assert_matches_type(SyncSkipLimit[ReturnEnvelope], return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: PostGrid) -> None: + with client.print_mail.return_envelopes.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + return_envelope = response.parse() + assert_matches_type(SyncSkipLimit[ReturnEnvelope], return_envelope, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncReturnEnvelopes: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create(self, async_client: AsyncPostGrid) -> None: + return_envelope = await async_client.print_mail.return_envelopes.create( + to="contact_kFjQtFqJtRXgahx5vgc9mA", + ) + assert_matches_type(ReturnEnvelope, return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_create_with_all_params(self, async_client: AsyncPostGrid) -> None: + return_envelope = await async_client.print_mail.return_envelopes.create( + to="contact_kFjQtFqJtRXgahx5vgc9mA", + description="description", + metadata={"foo": "bar"}, + idempotency_key="idempotency-key", + ) + assert_matches_type(ReturnEnvelope, return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_create(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.return_envelopes.with_raw_response.create( + to="contact_kFjQtFqJtRXgahx5vgc9mA", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + return_envelope = await response.parse() + assert_matches_type(ReturnEnvelope, return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_create(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.return_envelopes.with_streaming_response.create( + to="contact_kFjQtFqJtRXgahx5vgc9mA", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + return_envelope = await response.parse() + assert_matches_type(ReturnEnvelope, return_envelope, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncPostGrid) -> None: + return_envelope = await async_client.print_mail.return_envelopes.retrieve( + "id", + ) + assert_matches_type(ReturnEnvelope, return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.return_envelopes.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + return_envelope = await response.parse() + assert_matches_type(ReturnEnvelope, return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.return_envelopes.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + return_envelope = await response.parse() + assert_matches_type(ReturnEnvelope, return_envelope, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncPostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.print_mail.return_envelopes.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncPostGrid) -> None: + return_envelope = await async_client.print_mail.return_envelopes.list() + assert_matches_type(AsyncSkipLimit[ReturnEnvelope], return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncPostGrid) -> None: + return_envelope = await async_client.print_mail.return_envelopes.list( + limit=0, + search="search", + skip=0, + ) + assert_matches_type(AsyncSkipLimit[ReturnEnvelope], return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncPostGrid) -> None: + response = await async_client.print_mail.return_envelopes.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + return_envelope = await response.parse() + assert_matches_type(AsyncSkipLimit[ReturnEnvelope], return_envelope, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncPostGrid) -> None: + async with async_client.print_mail.return_envelopes.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + return_envelope = await response.parse() + assert_matches_type(AsyncSkipLimit[ReturnEnvelope], return_envelope, path=["response"]) + + assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/print_mail/test_self_mailers.py b/tests/api_resources/print_mail/test_self_mailers.py index 4746aa0..9b9336d 100644 --- a/tests/api_resources/print_mail/test_self_mailers.py +++ b/tests/api_resources/print_mail/test_self_mailers.py @@ -62,6 +62,7 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, inside_html="insideHTML", @@ -83,6 +84,7 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -183,6 +185,7 @@ def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, inside_template="insideTemplate", @@ -204,6 +207,7 @@ def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -303,6 +307,7 @@ def test_method_create_with_all_params_overload_3(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, pdf="https://example.com", @@ -323,6 +328,7 @@ def test_method_create_with_all_params_overload_3(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -420,6 +426,7 @@ def test_method_create_with_all_params_overload_4(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, pdf="U3RhaW5sZXNzIHJvY2tz", @@ -440,6 +447,7 @@ def test_method_create_with_all_params_overload_4(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -750,6 +758,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, inside_html="insideHTML", @@ -771,6 +780,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -871,6 +881,7 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, inside_template="insideTemplate", @@ -892,6 +903,7 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -991,6 +1003,7 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, pdf="https://example.com", @@ -1011,6 +1024,7 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -1108,6 +1122,7 @@ async def test_method_create_with_all_params_overload_4(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, pdf="U3RhaW5sZXNzIHJvY2tz", @@ -1128,6 +1143,7 @@ async def test_method_create_with_all_params_overload_4(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", diff --git a/tests/api_resources/print_mail/test_snap_packs.py b/tests/api_resources/print_mail/test_snap_packs.py index 7e849f9..0b74ae2 100644 --- a/tests/api_resources/print_mail/test_snap_packs.py +++ b/tests/api_resources/print_mail/test_snap_packs.py @@ -66,6 +66,7 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, inside_html="insideHTML", @@ -87,6 +88,7 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -187,6 +189,7 @@ def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, inside_template="insideTemplate", @@ -208,6 +211,7 @@ def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -307,6 +311,7 @@ def test_method_create_with_all_params_overload_3(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, pdf="https://example.com", @@ -327,6 +332,7 @@ def test_method_create_with_all_params_overload_3(self, client: PostGrid) -> Non "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -639,6 +645,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, inside_html="insideHTML", @@ -660,6 +667,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -760,6 +768,7 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, inside_template="insideTemplate", @@ -781,6 +790,7 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", @@ -880,6 +890,7 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, pdf="https://example.com", @@ -900,6 +911,7 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn "phone_number": "phoneNumber", "postal_or_zip": "postalOrZip", "province_or_state": "provinceOrState", + "secret": True, "skip_verification": True, }, description="description", diff --git a/tests/api_resources/test_bulk_verification.py b/tests/api_resources/test_bulk_verification.py new file mode 100644 index 0000000..9a23dcd --- /dev/null +++ b/tests/api_resources/test_bulk_verification.py @@ -0,0 +1,318 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from __future__ import annotations + +import os +from typing import Any, cast + +import pytest + +from postgrid import PostGrid, AsyncPostGrid +from tests.utils import assert_matches_type +from postgrid.types import ( + BulkVerificationListResponse, + BulkVerificationUploadResponse, + BulkVerificationRetrieveResponse, +) + +base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") + + +class TestBulkVerification: + parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_retrieve(self, client: PostGrid) -> None: + bulk_verification = client.bulk_verification.retrieve( + "id", + ) + assert_matches_type(BulkVerificationRetrieveResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_retrieve(self, client: PostGrid) -> None: + response = client.bulk_verification.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk_verification = response.parse() + assert_matches_type(BulkVerificationRetrieveResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_retrieve(self, client: PostGrid) -> None: + with client.bulk_verification.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk_verification = response.parse() + assert_matches_type(BulkVerificationRetrieveResponse, bulk_verification, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_path_params_retrieve(self, client: PostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + client.bulk_verification.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list(self, client: PostGrid) -> None: + bulk_verification = client.bulk_verification.list() + assert_matches_type(BulkVerificationListResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_list_with_all_params(self, client: PostGrid) -> None: + bulk_verification = client.bulk_verification.list( + limit=0, + skip=0, + ) + assert_matches_type(BulkVerificationListResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_list(self, client: PostGrid) -> None: + response = client.bulk_verification.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk_verification = response.parse() + assert_matches_type(BulkVerificationListResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_list(self, client: PostGrid) -> None: + with client.bulk_verification.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk_verification = response.parse() + assert_matches_type(BulkVerificationListResponse, bulk_verification, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_upload(self, client: PostGrid) -> None: + bulk_verification = client.bulk_verification.upload( + file=b"Example data", + mappings={"line1": "line1"}, + name="name", + ) + assert_matches_type(BulkVerificationUploadResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_method_upload_with_all_params(self, client: PostGrid) -> None: + bulk_verification = client.bulk_verification.upload( + file=b"Example data", + mappings={ + "line1": "line1", + "city": "city", + "country": "country", + "first_name": "firstName", + "full_name": "fullName", + "last_name": "lastName", + "line2": "line2", + "postal_or_zip": "postalOrZip", + "province_or_state": "provinceOrState", + }, + name="name", + default_country="defaultCountry", + run_ccoa=True, + run_ncoa=True, + use_geocode=True, + use_intl_verification=True, + use_proper_case=True, + ) + assert_matches_type(BulkVerificationUploadResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_raw_response_upload(self, client: PostGrid) -> None: + response = client.bulk_verification.with_raw_response.upload( + file=b"Example data", + mappings={"line1": "line1"}, + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk_verification = response.parse() + assert_matches_type(BulkVerificationUploadResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + def test_streaming_response_upload(self, client: PostGrid) -> None: + with client.bulk_verification.with_streaming_response.upload( + file=b"Example data", + mappings={"line1": "line1"}, + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk_verification = response.parse() + assert_matches_type(BulkVerificationUploadResponse, bulk_verification, path=["response"]) + + assert cast(Any, response.is_closed) is True + + +class TestAsyncBulkVerification: + parametrize = pytest.mark.parametrize( + "async_client", [False, True, {"http_client": "aiohttp"}], indirect=True, ids=["loose", "strict", "aiohttp"] + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_retrieve(self, async_client: AsyncPostGrid) -> None: + bulk_verification = await async_client.bulk_verification.retrieve( + "id", + ) + assert_matches_type(BulkVerificationRetrieveResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_retrieve(self, async_client: AsyncPostGrid) -> None: + response = await async_client.bulk_verification.with_raw_response.retrieve( + "id", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk_verification = await response.parse() + assert_matches_type(BulkVerificationRetrieveResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_retrieve(self, async_client: AsyncPostGrid) -> None: + async with async_client.bulk_verification.with_streaming_response.retrieve( + "id", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk_verification = await response.parse() + assert_matches_type(BulkVerificationRetrieveResponse, bulk_verification, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_path_params_retrieve(self, async_client: AsyncPostGrid) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `id` but received ''"): + await async_client.bulk_verification.with_raw_response.retrieve( + "", + ) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list(self, async_client: AsyncPostGrid) -> None: + bulk_verification = await async_client.bulk_verification.list() + assert_matches_type(BulkVerificationListResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_list_with_all_params(self, async_client: AsyncPostGrid) -> None: + bulk_verification = await async_client.bulk_verification.list( + limit=0, + skip=0, + ) + assert_matches_type(BulkVerificationListResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_list(self, async_client: AsyncPostGrid) -> None: + response = await async_client.bulk_verification.with_raw_response.list() + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk_verification = await response.parse() + assert_matches_type(BulkVerificationListResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_list(self, async_client: AsyncPostGrid) -> None: + async with async_client.bulk_verification.with_streaming_response.list() as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk_verification = await response.parse() + assert_matches_type(BulkVerificationListResponse, bulk_verification, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_upload(self, async_client: AsyncPostGrid) -> None: + bulk_verification = await async_client.bulk_verification.upload( + file=b"Example data", + mappings={"line1": "line1"}, + name="name", + ) + assert_matches_type(BulkVerificationUploadResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_method_upload_with_all_params(self, async_client: AsyncPostGrid) -> None: + bulk_verification = await async_client.bulk_verification.upload( + file=b"Example data", + mappings={ + "line1": "line1", + "city": "city", + "country": "country", + "first_name": "firstName", + "full_name": "fullName", + "last_name": "lastName", + "line2": "line2", + "postal_or_zip": "postalOrZip", + "province_or_state": "provinceOrState", + }, + name="name", + default_country="defaultCountry", + run_ccoa=True, + run_ncoa=True, + use_geocode=True, + use_intl_verification=True, + use_proper_case=True, + ) + assert_matches_type(BulkVerificationUploadResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_raw_response_upload(self, async_client: AsyncPostGrid) -> None: + response = await async_client.bulk_verification.with_raw_response.upload( + file=b"Example data", + mappings={"line1": "line1"}, + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + bulk_verification = await response.parse() + assert_matches_type(BulkVerificationUploadResponse, bulk_verification, path=["response"]) + + @pytest.mark.skip(reason="Mock server tests are disabled") + @parametrize + async def test_streaming_response_upload(self, async_client: AsyncPostGrid) -> None: + async with async_client.bulk_verification.with_streaming_response.upload( + file=b"Example data", + mappings={"line1": "line1"}, + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + bulk_verification = await response.parse() + assert_matches_type(BulkVerificationUploadResponse, bulk_verification, path=["response"]) + + assert cast(Any, response.is_closed) is True From 6d2ab69231ab511d841c2fb914159513d1c64c27 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 22:08:40 +0000 Subject: [PATCH 6/7] feat: PE-6131 HOTFIX: Fix idempotency key header for create endpoints --- .stats.yml | 6 +- api.md | 28 +- .../resources/print_mail/campaigns.py | 111 +++++--- src/postgrid/resources/print_mail/cheques.py | 143 +++++----- src/postgrid/resources/print_mail/letters.py | 231 ++++++++++------ .../resources/print_mail/postcards.py | 251 +++++++++++------- .../resources/print_mail/self_mailers.py | 247 ++++++++++------- .../resources/print_mail/snap_packs.py | 221 +++++++++------ src/postgrid/types/print_mail/__init__.py | 8 +- src/postgrid/types/print_mail/attached_pdf.py | 3 +- .../types/print_mail/attached_pdf_param.py | 5 +- .../print_mail/campaign_create_params.py | 16 +- .../print_mail/campaign_update_params.py | 16 +- .../types/print_mail/cheque_create_params.py | 6 +- .../types/print_mail/letter_create_params.py | 9 +- .../print_mail/letter_create_response.py | 10 + src/postgrid/types/print_mail/plastic_card.py | 6 +- .../types/print_mail/plastic_card_param.py | 6 +- .../print_mail/postcard_create_params.py | 18 +- .../print_mail/postcard_create_response.py | 10 + .../print_mail/self_mailer_create_params.py | 18 +- .../print_mail/self_mailer_create_response.py | 10 + ...nap_pack_list_response.py => snap_pack.py} | 4 +- .../print_mail/snap_pack_create_params.py | 9 +- .../print_mail/snap_pack_create_response.py | 196 +------------- .../print_mail/snap_pack_delete_response.py | 196 -------------- .../snap_pack_progressions_response.py | 196 -------------- .../print_mail/snap_pack_retrieve_response.py | 196 -------------- .../print_mail/test_campaigns.py | 8 +- .../api_resources/print_mail/test_cheques.py | 6 +- .../api_resources/print_mail/test_letters.py | 55 ++-- .../print_mail/test_postcards.py | 89 ++++--- .../print_mail/test_self_mailers.py | 89 ++++--- .../print_mail/test_snap_packs.py | 63 ++--- 34 files changed, 1059 insertions(+), 1427 deletions(-) create mode 100644 src/postgrid/types/print_mail/letter_create_response.py create mode 100644 src/postgrid/types/print_mail/postcard_create_response.py create mode 100644 src/postgrid/types/print_mail/self_mailer_create_response.py rename src/postgrid/types/print_mail/{snap_pack_list_response.py => snap_pack.py} (98%) delete mode 100644 src/postgrid/types/print_mail/snap_pack_delete_response.py delete mode 100644 src/postgrid/types/print_mail/snap_pack_progressions_response.py delete mode 100644 src/postgrid/types/print_mail/snap_pack_retrieve_response.py diff --git a/.stats.yml b/.stats.yml index 86116e6..a18e8eb 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 137 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/postgrid/postgrid-32126b0df875e75e2a33a809e6fc25ea55cedc0d2505450361e71f4f2cedecf3.yml -openapi_spec_hash: 2cc8c911382f942c07b624e45c8db026 -config_hash: 6398155ff41b9bcbc09dc6066a1bf113 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/postgrid/postgrid-a1e82d54f9c6456622ef353b6864dd9ccc47c9b5cf6b5fbe98c123f2bdf30f34.yml +openapi_spec_hash: cd682fda35a9733c4bcd508b8d8e6eab +config_hash: f16e8e5b59ab878eee700d0f2dee5645 diff --git a/api.md b/api.md index 39148f0..70255a3 100644 --- a/api.md +++ b/api.md @@ -174,13 +174,14 @@ from postgrid.types.print_mail import ( Letter, LetterSize, PlasticCard, + LetterCreateResponse, LetterRetrieveURLResponse, ) ``` Methods: -- client.print_mail.letters.create(\*\*params) -> Letter +- client.print_mail.letters.create(\*\*params) -> LetterCreateResponse - client.print_mail.letters.retrieve(id) -> Letter - client.print_mail.letters.list(\*\*params) -> SyncSkipLimit[Letter] - client.print_mail.letters.delete(id) -> Letter @@ -193,12 +194,12 @@ Methods: Types: ```python -from postgrid.types.print_mail import Postcard, PostcardRetrieveURLResponse +from postgrid.types.print_mail import Postcard, PostcardCreateResponse, PostcardRetrieveURLResponse ``` Methods: -- client.print_mail.postcards.create(\*\*params) -> Postcard +- client.print_mail.postcards.create(\*\*params) -> PostcardCreateResponse - client.print_mail.postcards.retrieve(id) -> Postcard - client.print_mail.postcards.list(\*\*params) -> SyncSkipLimit[Postcard] - client.print_mail.postcards.delete(id) -> Postcard @@ -245,12 +246,16 @@ Methods: Types: ```python -from postgrid.types.print_mail import SelfMailer, SelfMailerRetrieveURLResponse +from postgrid.types.print_mail import ( + SelfMailer, + SelfMailerCreateResponse, + SelfMailerRetrieveURLResponse, +) ``` Methods: -- client.print_mail.self_mailers.create(\*\*params) -> SelfMailer +- client.print_mail.self_mailers.create(\*\*params) -> SelfMailerCreateResponse - client.print_mail.self_mailers.retrieve(id) -> SelfMailer - client.print_mail.self_mailers.list(\*\*params) -> SyncSkipLimit[SelfMailer] - client.print_mail.self_mailers.delete(id) -> SelfMailer @@ -433,11 +438,8 @@ Types: ```python from postgrid.types.print_mail import ( + SnapPack, SnapPackCreateResponse, - SnapPackRetrieveResponse, - SnapPackListResponse, - SnapPackDeleteResponse, - SnapPackProgressionsResponse, SnapPackRetrieveCapabilitiesResponse, ) ``` @@ -445,10 +447,10 @@ from postgrid.types.print_mail import ( Methods: - client.print_mail.snap_packs.create(\*\*params) -> SnapPackCreateResponse -- client.print_mail.snap_packs.retrieve(id) -> SnapPackRetrieveResponse -- client.print_mail.snap_packs.list(\*\*params) -> SyncSkipLimit[SnapPackListResponse] -- client.print_mail.snap_packs.delete(id) -> SnapPackDeleteResponse -- client.print_mail.snap_packs.progressions(id) -> SnapPackProgressionsResponse +- client.print_mail.snap_packs.retrieve(id) -> SnapPack +- client.print_mail.snap_packs.list(\*\*params) -> SyncSkipLimit[SnapPack] +- client.print_mail.snap_packs.delete(id) -> SnapPack +- client.print_mail.snap_packs.progressions(id) -> SnapPack - client.print_mail.snap_packs.retrieve_capabilities(\*\*params) -> SnapPackRetrieveCapabilitiesResponse ## TargetedListBuilds diff --git a/src/postgrid/resources/print_mail/campaigns.py b/src/postgrid/resources/print_mail/campaigns.py index f7f7a69..b108af1 100644 --- a/src/postgrid/resources/print_mail/campaigns.py +++ b/src/postgrid/resources/print_mail/campaigns.py @@ -2,13 +2,14 @@ from __future__ import annotations -from typing import Dict, Union, Optional +from typing import Dict, Union, Mapping, Optional, cast from datetime import datetime import httpx +from ..._files import deepcopy_with_paths from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, maybe_transform, strip_not_given, async_maybe_transform +from ..._utils import extract_files, path_template, maybe_transform, strip_not_given, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -124,23 +125,46 @@ def create( timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {**strip_not_given({"idempotency-key": idempotency_key}), **(extra_headers or {})} + body = deepcopy_with_paths( + { + "mailing_list": mailing_list, + "cheque": cheque, + "default_sender_contact": default_sender_contact, + "description": description, + "letter": letter, + "metadata": metadata, + "postcard": postcard, + "self_mailer": self_mailer, + "send_date": send_date, + "snap_pack": snap_pack, + }, + [ + ["letter", "pdf"], + ["postcard", "pdf"], + ["cheque", "letterPDF"], + ["selfMailer", "pdf"], + ["snapPack", "pdf"], + ], + ) + files = extract_files( + cast(Mapping[str, object], body), + paths=[ + ["letter", "pdf"], + ["postcard", "pdf"], + ["cheque", "letterPDF"], + ["selfMailer", "pdf"], + ["snapPack", "pdf"], + ], + ) + if files: + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( "/print-mail/v1/campaigns", - body=maybe_transform( - { - "mailing_list": mailing_list, - "cheque": cheque, - "default_sender_contact": default_sender_contact, - "description": description, - "letter": letter, - "metadata": metadata, - "postcard": postcard, - "self_mailer": self_mailer, - "send_date": send_date, - "snap_pack": snap_pack, - }, - campaign_create_params.CampaignCreateParams, - ), + body=maybe_transform(body, campaign_create_params.CampaignCreateParams), + files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -492,23 +516,46 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ extra_headers = {**strip_not_given({"idempotency-key": idempotency_key}), **(extra_headers or {})} + body = deepcopy_with_paths( + { + "mailing_list": mailing_list, + "cheque": cheque, + "default_sender_contact": default_sender_contact, + "description": description, + "letter": letter, + "metadata": metadata, + "postcard": postcard, + "self_mailer": self_mailer, + "send_date": send_date, + "snap_pack": snap_pack, + }, + [ + ["letter", "pdf"], + ["postcard", "pdf"], + ["cheque", "letterPDF"], + ["selfMailer", "pdf"], + ["snapPack", "pdf"], + ], + ) + files = extract_files( + cast(Mapping[str, object], body), + paths=[ + ["letter", "pdf"], + ["postcard", "pdf"], + ["cheque", "letterPDF"], + ["selfMailer", "pdf"], + ["snapPack", "pdf"], + ], + ) + if files: + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( "/print-mail/v1/campaigns", - body=await async_maybe_transform( - { - "mailing_list": mailing_list, - "cheque": cheque, - "default_sender_contact": default_sender_contact, - "description": description, - "letter": letter, - "metadata": metadata, - "postcard": postcard, - "self_mailer": self_mailer, - "send_date": send_date, - "snap_pack": snap_pack, - }, - campaign_create_params.CampaignCreateParams, - ), + body=await async_maybe_transform(body, campaign_create_params.CampaignCreateParams), + files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/postgrid/resources/print_mail/cheques.py b/src/postgrid/resources/print_mail/cheques.py index adf639b..786de7a 100644 --- a/src/postgrid/resources/print_mail/cheques.py +++ b/src/postgrid/resources/print_mail/cheques.py @@ -2,14 +2,15 @@ from __future__ import annotations -from typing import Dict, Union +from typing import Dict, Union, Mapping, cast from datetime import datetime from typing_extensions import Literal import httpx -from ..._types import Body, Omit, Query, Headers, NotGiven, Base64FileInput, omit, not_given -from ..._utils import path_template, maybe_transform, async_maybe_transform +from ..._files import deepcopy_with_paths +from ..._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given +from ..._utils import extract_files, path_template, maybe_transform, strip_not_given, async_maybe_transform from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -63,7 +64,7 @@ def create( digital_only: DigitalOnlyParam | Omit = omit, envelope: Union[Literal["standard"], str] | Omit = omit, letter_html: str | Omit = omit, - letter_pdf: Union[str, Base64FileInput] | Omit = omit, + letter_pdf: Union[str, FileTypes] | Omit = omit, letter_settings: cheque_create_params.LetterSettings | Omit = omit, letter_template: str | Omit = omit, logo: str | Omit = omit, @@ -105,6 +106,7 @@ def create( return_envelope: str | Omit = omit, send_date: Union[str, datetime] | Omit = omit, size: ChequeSize | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -221,36 +223,45 @@ def create( timeout: Override the client-level default timeout for this request, in seconds """ + extra_headers = {**strip_not_given({"idempotency-key": idempotency_key}), **(extra_headers or {})} + body = deepcopy_with_paths( + { + "amount": amount, + "bank_account": bank_account, + "from_": from_, + "to": to, + "currency_code": currency_code, + "description": description, + "digital_only": digital_only, + "envelope": envelope, + "letter_html": letter_html, + "letter_pdf": letter_pdf, + "letter_settings": letter_settings, + "letter_template": letter_template, + "logo": logo, + "mailing_class": mailing_class, + "memo": memo, + "merge_variables": merge_variables, + "message": message, + "metadata": metadata, + "number": number, + "redirect_to": redirect_to, + "return_envelope": return_envelope, + "send_date": send_date, + "size": size, + }, + [["letterPDF"]], + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["letterPDF"]]) + if files: + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return self._post( "/print-mail/v1/cheques", - body=maybe_transform( - { - "amount": amount, - "bank_account": bank_account, - "from_": from_, - "to": to, - "currency_code": currency_code, - "description": description, - "digital_only": digital_only, - "envelope": envelope, - "letter_html": letter_html, - "letter_pdf": letter_pdf, - "letter_settings": letter_settings, - "letter_template": letter_template, - "logo": logo, - "mailing_class": mailing_class, - "memo": memo, - "merge_variables": merge_variables, - "message": message, - "metadata": metadata, - "number": number, - "redirect_to": redirect_to, - "return_envelope": return_envelope, - "send_date": send_date, - "size": size, - }, - cheque_create_params.ChequeCreateParams, - ), + body=maybe_transform(body, cheque_create_params.ChequeCreateParams), + files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -561,7 +572,7 @@ async def create( digital_only: DigitalOnlyParam | Omit = omit, envelope: Union[Literal["standard"], str] | Omit = omit, letter_html: str | Omit = omit, - letter_pdf: Union[str, Base64FileInput] | Omit = omit, + letter_pdf: Union[str, FileTypes] | Omit = omit, letter_settings: cheque_create_params.LetterSettings | Omit = omit, letter_template: str | Omit = omit, logo: str | Omit = omit, @@ -603,6 +614,7 @@ async def create( return_envelope: str | Omit = omit, send_date: Union[str, datetime] | Omit = omit, size: ChequeSize | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -719,36 +731,45 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ + extra_headers = {**strip_not_given({"idempotency-key": idempotency_key}), **(extra_headers or {})} + body = deepcopy_with_paths( + { + "amount": amount, + "bank_account": bank_account, + "from_": from_, + "to": to, + "currency_code": currency_code, + "description": description, + "digital_only": digital_only, + "envelope": envelope, + "letter_html": letter_html, + "letter_pdf": letter_pdf, + "letter_settings": letter_settings, + "letter_template": letter_template, + "logo": logo, + "mailing_class": mailing_class, + "memo": memo, + "merge_variables": merge_variables, + "message": message, + "metadata": metadata, + "number": number, + "redirect_to": redirect_to, + "return_envelope": return_envelope, + "send_date": send_date, + "size": size, + }, + [["letterPDF"]], + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["letterPDF"]]) + if files: + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} return await self._post( "/print-mail/v1/cheques", - body=await async_maybe_transform( - { - "amount": amount, - "bank_account": bank_account, - "from_": from_, - "to": to, - "currency_code": currency_code, - "description": description, - "digital_only": digital_only, - "envelope": envelope, - "letter_html": letter_html, - "letter_pdf": letter_pdf, - "letter_settings": letter_settings, - "letter_template": letter_template, - "logo": logo, - "mailing_class": mailing_class, - "memo": memo, - "merge_variables": merge_variables, - "message": message, - "metadata": metadata, - "number": number, - "redirect_to": redirect_to, - "return_envelope": return_envelope, - "send_date": send_date, - "size": size, - }, - cheque_create_params.ChequeCreateParams, - ), + body=await async_maybe_transform(body, cheque_create_params.ChequeCreateParams), + files=files, options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), diff --git a/src/postgrid/resources/print_mail/letters.py b/src/postgrid/resources/print_mail/letters.py index a680590..002920e 100644 --- a/src/postgrid/resources/print_mail/letters.py +++ b/src/postgrid/resources/print_mail/letters.py @@ -2,14 +2,22 @@ from __future__ import annotations -from typing import Dict, Union +from typing import Any, Dict, Union, Mapping, cast from datetime import datetime from typing_extensions import Literal, overload import httpx -from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, required_args, maybe_transform, async_maybe_transform +from ..._files import deepcopy_with_paths +from ..._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given +from ..._utils import ( + extract_files, + path_template, + required_args, + maybe_transform, + strip_not_given, + async_maybe_transform, +) from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -32,6 +40,7 @@ from ...types.print_mail.address_placement import AddressPlacement from ...types.print_mail.attached_pdf_param import AttachedPdfParam from ...types.print_mail.plastic_card_param import PlasticCardParam +from ...types.print_mail.letter_create_response import LetterCreateResponse from ...types.print_mail.letter_retrieve_url_response import LetterRetrieveURLResponse __all__ = ["LettersResource", "AsyncLettersResource"] @@ -113,21 +122,24 @@ def create( return_envelope: str | Omit = omit, send_date: Union[str, datetime] | Omit = omit, size: LetterSize | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Letter: + ) -> LetterCreateResponse: """Create a letter. Note that you can supply one of the following: - HTML content for the letter - A template ID for the letter - - A URL or file for a PDF for the letter - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a PDF for the letter Create a letter via a multipart/form-data + request. Accepts the same fields as the JSON create body (nested objects are + bracket-encoded form fields, e.g. `to[firstName]`); use this content type to + upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -252,21 +264,24 @@ def create( return_envelope: str | Omit = omit, send_date: Union[str, datetime] | Omit = omit, size: LetterSize | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Letter: + ) -> LetterCreateResponse: """Create a letter. Note that you can supply one of the following: - HTML content for the letter - A template ID for the letter - - A URL or file for a PDF for the letter - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a PDF for the letter Create a letter via a multipart/form-data + request. Accepts the same fields as the JSON create body (nested objects are + bracket-encoded form fields, e.g. `to[firstName]`); use this content type to + upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -342,7 +357,7 @@ def create( self, *, from_: letter_create_params.LetterCreateWithPdfFrom, - pdf: str, + pdf: Union[str, FileTypes], to: letter_create_params.LetterCreateWithPdfTo, address_placement: AddressPlacement | Omit = omit, attached_pdf: AttachedPdfParam | Omit = omit, @@ -391,21 +406,24 @@ def create( return_envelope: str | Omit = omit, send_date: Union[str, datetime] | Omit = omit, size: LetterSize | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Letter: + ) -> LetterCreateResponse: """Create a letter. Note that you can supply one of the following: - HTML content for the letter - A template ID for the letter - - A URL or file for a PDF for the letter - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a PDF for the letter Create a letter via a multipart/form-data + request. Accepts the same fields as the JSON create body (nested objects are + bracket-encoded form fields, e.g. `to[firstName]`); use this content type to + upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -533,46 +551,61 @@ def create( return_envelope: str | Omit = omit, send_date: Union[str, datetime] | Omit = omit, size: LetterSize | Omit = omit, + idempotency_key: str | Omit = omit, template: str | Omit = omit, - pdf: str | Omit = omit, + pdf: Union[str, FileTypes] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Letter: - return self._post( - "/print-mail/v1/letters", - body=maybe_transform( - { - "from_": from_, - "html": html, - "to": to, - "address_placement": address_placement, - "attached_pdf": attached_pdf, - "color": color, - "description": description, - "double_sided": double_sided, - "envelope": envelope, - "mailing_class": mailing_class, - "merge_variables": merge_variables, - "metadata": metadata, - "paper": paper, - "perforated_page": perforated_page, - "plastic_card": plastic_card, - "return_envelope": return_envelope, - "send_date": send_date, - "size": size, - "template": template, - "pdf": pdf, - }, - letter_create_params.LetterCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ) -> LetterCreateResponse: + extra_headers = {**strip_not_given({"idempotency-key": idempotency_key}), **(extra_headers or {})} + body = deepcopy_with_paths( + { + "from_": from_, + "html": html, + "to": to, + "address_placement": address_placement, + "attached_pdf": attached_pdf, + "color": color, + "description": description, + "double_sided": double_sided, + "envelope": envelope, + "mailing_class": mailing_class, + "merge_variables": merge_variables, + "metadata": metadata, + "paper": paper, + "perforated_page": perforated_page, + "plastic_card": plastic_card, + "return_envelope": return_envelope, + "send_date": send_date, + "size": size, + "template": template, + "pdf": pdf, + }, + [["pdf"]], + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["pdf"]]) + if files: + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return cast( + LetterCreateResponse, + self._post( + "/print-mail/v1/letters", + body=maybe_transform(body, letter_create_params.LetterCreateParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, LetterCreateResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=Letter, ) def retrieve( @@ -884,21 +917,24 @@ async def create( return_envelope: str | Omit = omit, send_date: Union[str, datetime] | Omit = omit, size: LetterSize | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Letter: + ) -> LetterCreateResponse: """Create a letter. Note that you can supply one of the following: - HTML content for the letter - A template ID for the letter - - A URL or file for a PDF for the letter - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a PDF for the letter Create a letter via a multipart/form-data + request. Accepts the same fields as the JSON create body (nested objects are + bracket-encoded form fields, e.g. `to[firstName]`); use this content type to + upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -1023,21 +1059,24 @@ async def create( return_envelope: str | Omit = omit, send_date: Union[str, datetime] | Omit = omit, size: LetterSize | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Letter: + ) -> LetterCreateResponse: """Create a letter. Note that you can supply one of the following: - HTML content for the letter - A template ID for the letter - - A URL or file for a PDF for the letter - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a PDF for the letter Create a letter via a multipart/form-data + request. Accepts the same fields as the JSON create body (nested objects are + bracket-encoded form fields, e.g. `to[firstName]`); use this content type to + upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -1113,7 +1152,7 @@ async def create( self, *, from_: letter_create_params.LetterCreateWithPdfFrom, - pdf: str, + pdf: Union[str, FileTypes], to: letter_create_params.LetterCreateWithPdfTo, address_placement: AddressPlacement | Omit = omit, attached_pdf: AttachedPdfParam | Omit = omit, @@ -1162,21 +1201,24 @@ async def create( return_envelope: str | Omit = omit, send_date: Union[str, datetime] | Omit = omit, size: LetterSize | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Letter: + ) -> LetterCreateResponse: """Create a letter. Note that you can supply one of the following: - HTML content for the letter - A template ID for the letter - - A URL or file for a PDF for the letter - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a PDF for the letter Create a letter via a multipart/form-data + request. Accepts the same fields as the JSON create body (nested objects are + bracket-encoded form fields, e.g. `to[firstName]`); use this content type to + upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -1304,46 +1346,61 @@ async def create( return_envelope: str | Omit = omit, send_date: Union[str, datetime] | Omit = omit, size: LetterSize | Omit = omit, + idempotency_key: str | Omit = omit, template: str | Omit = omit, - pdf: str | Omit = omit, + pdf: Union[str, FileTypes] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Letter: - return await self._post( - "/print-mail/v1/letters", - body=await async_maybe_transform( - { - "from_": from_, - "html": html, - "to": to, - "address_placement": address_placement, - "attached_pdf": attached_pdf, - "color": color, - "description": description, - "double_sided": double_sided, - "envelope": envelope, - "mailing_class": mailing_class, - "merge_variables": merge_variables, - "metadata": metadata, - "paper": paper, - "perforated_page": perforated_page, - "plastic_card": plastic_card, - "return_envelope": return_envelope, - "send_date": send_date, - "size": size, - "template": template, - "pdf": pdf, - }, - letter_create_params.LetterCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ) -> LetterCreateResponse: + extra_headers = {**strip_not_given({"idempotency-key": idempotency_key}), **(extra_headers or {})} + body = deepcopy_with_paths( + { + "from_": from_, + "html": html, + "to": to, + "address_placement": address_placement, + "attached_pdf": attached_pdf, + "color": color, + "description": description, + "double_sided": double_sided, + "envelope": envelope, + "mailing_class": mailing_class, + "merge_variables": merge_variables, + "metadata": metadata, + "paper": paper, + "perforated_page": perforated_page, + "plastic_card": plastic_card, + "return_envelope": return_envelope, + "send_date": send_date, + "size": size, + "template": template, + "pdf": pdf, + }, + [["pdf"]], + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["pdf"]]) + if files: + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return cast( + LetterCreateResponse, + await self._post( + "/print-mail/v1/letters", + body=await async_maybe_transform(body, letter_create_params.LetterCreateParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, LetterCreateResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=Letter, ) async def retrieve( diff --git a/src/postgrid/resources/print_mail/postcards.py b/src/postgrid/resources/print_mail/postcards.py index aef077e..c023d95 100644 --- a/src/postgrid/resources/print_mail/postcards.py +++ b/src/postgrid/resources/print_mail/postcards.py @@ -2,14 +2,22 @@ from __future__ import annotations -from typing import Dict, Union +from typing import Any, Dict, Union, Mapping, cast from datetime import datetime from typing_extensions import Literal, overload import httpx -from ..._types import Body, Omit, Query, Headers, NotGiven, Base64FileInput, omit, not_given -from ..._utils import path_template, required_args, maybe_transform, async_maybe_transform +from ..._files import deepcopy_with_paths +from ..._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given +from ..._utils import ( + extract_files, + path_template, + required_args, + maybe_transform, + strip_not_given, + async_maybe_transform, +) from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -22,6 +30,7 @@ from ..._base_client import AsyncPaginator, make_request_options from ...types.print_mail import postcard_list_params, postcard_cancel_params, postcard_create_params from ...types.print_mail.postcard import Postcard +from ...types.print_mail.postcard_create_response import PostcardCreateResponse from ...types.print_mail.postcard_retrieve_url_response import PostcardRetrieveURLResponse __all__ = ["PostcardsResource", "AsyncPostcardsResource"] @@ -102,22 +111,25 @@ def create( ] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Postcard: + ) -> PostcardCreateResponse: """Create a postcard. Note that you can supply one of the following: - HTML content for the front and back of the postcard - A template ID for the front and back of the postcard - - A URL or file for a 2 page PDF where the first page is the front of the - postcard and the second page is the back - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the front of the postcard and + the second page is the back Create a postcard via a multipart/form-data + request. Accepts the same fields as the JSON create body (nested objects are + bracket-encoded form fields, e.g. `to[firstName]`); use this content type to + upload the PDF file directly. Args: back_html: The HTML content for the back of the postcard. You can supply _either_ this or @@ -230,22 +242,25 @@ def create( ] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Postcard: + ) -> PostcardCreateResponse: """Create a postcard. Note that you can supply one of the following: - HTML content for the front and back of the postcard - A template ID for the front and back of the postcard - - A URL or file for a 2 page PDF where the first page is the front of the - postcard and the second page is the back - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the front of the postcard and + the second page is the back Create a postcard via a multipart/form-data + request. Accepts the same fields as the JSON create body (nested objects are + bracket-encoded form fields, e.g. `to[firstName]`); use this content type to + upload the PDF file directly. Args: back_template: The template ID for the back of the postcard. You can supply _either_ this or @@ -357,22 +372,25 @@ def create( ] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Postcard: + ) -> PostcardCreateResponse: """Create a postcard. Note that you can supply one of the following: - HTML content for the front and back of the postcard - A template ID for the front and back of the postcard - - A URL or file for a 2 page PDF where the first page is the front of the - postcard and the second page is the back - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the front of the postcard and + the second page is the back Create a postcard via a multipart/form-data + request. Accepts the same fields as the JSON create body (nested objects are + bracket-encoded form fields, e.g. `to[firstName]`); use this content type to + upload the PDF file directly. Args: pdf: A URL pointing to a 2 page PDF file. The first page is the front of the postcard @@ -433,7 +451,7 @@ def create( def create( self, *, - pdf: Union[str, Base64FileInput], + pdf: FileTypes, size: Literal["6x4", "9x6", "11x6"], to: postcard_create_params.PostcardCreateWithPdfFileTo, description: str | Omit = omit, @@ -481,26 +499,30 @@ def create( ] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Postcard: + ) -> PostcardCreateResponse: """Create a postcard. Note that you can supply one of the following: - HTML content for the front and back of the postcard - A template ID for the front and back of the postcard - - A URL or file for a 2 page PDF where the first page is the front of the - postcard and the second page is the back - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the front of the postcard and + the second page is the back Create a postcard via a multipart/form-data + request. Accepts the same fields as the JSON create body (nested objects are + bracket-encoded form fields, e.g. `to[firstName]`); use this content type to + upload the PDF file directly. Args: - pdf: A 2 page PDF file. The first page is the front of the postcard and the second - page is the back (where the address will be stamped on). + pdf: Represents a raw file upload. Sending the actual file requires a + `multipart/form-data` request; in `application/json` request bodies, supply a + URL instead. size: Enum representing the supported postcard sizes. @@ -617,41 +639,56 @@ def create( ] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, back_template: str | Omit = omit, front_template: str | Omit = omit, - pdf: str | Union[str, Base64FileInput] | Omit = omit, + pdf: str | FileTypes | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Postcard: - return self._post( - "/print-mail/v1/postcards", - body=maybe_transform( - { - "back_html": back_html, - "front_html": front_html, - "size": size, - "to": to, - "description": description, - "from_": from_, - "mailing_class": mailing_class, - "merge_variables": merge_variables, - "metadata": metadata, - "paper": paper, - "send_date": send_date, - "back_template": back_template, - "front_template": front_template, - "pdf": pdf, - }, - postcard_create_params.PostcardCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ) -> PostcardCreateResponse: + extra_headers = {**strip_not_given({"idempotency-key": idempotency_key}), **(extra_headers or {})} + body = deepcopy_with_paths( + { + "back_html": back_html, + "front_html": front_html, + "size": size, + "to": to, + "description": description, + "from_": from_, + "mailing_class": mailing_class, + "merge_variables": merge_variables, + "metadata": metadata, + "paper": paper, + "send_date": send_date, + "back_template": back_template, + "front_template": front_template, + "pdf": pdf, + }, + [["pdf"]], + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["pdf"]]) + if files: + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return cast( + PostcardCreateResponse, + self._post( + "/print-mail/v1/postcards", + body=maybe_transform(body, postcard_create_params.PostcardCreateParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, PostcardCreateResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=Postcard, ) def retrieve( @@ -962,22 +999,25 @@ async def create( ] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Postcard: + ) -> PostcardCreateResponse: """Create a postcard. Note that you can supply one of the following: - HTML content for the front and back of the postcard - A template ID for the front and back of the postcard - - A URL or file for a 2 page PDF where the first page is the front of the - postcard and the second page is the back - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the front of the postcard and + the second page is the back Create a postcard via a multipart/form-data + request. Accepts the same fields as the JSON create body (nested objects are + bracket-encoded form fields, e.g. `to[firstName]`); use this content type to + upload the PDF file directly. Args: back_html: The HTML content for the back of the postcard. You can supply _either_ this or @@ -1090,22 +1130,25 @@ async def create( ] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Postcard: + ) -> PostcardCreateResponse: """Create a postcard. Note that you can supply one of the following: - HTML content for the front and back of the postcard - A template ID for the front and back of the postcard - - A URL or file for a 2 page PDF where the first page is the front of the - postcard and the second page is the back - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the front of the postcard and + the second page is the back Create a postcard via a multipart/form-data + request. Accepts the same fields as the JSON create body (nested objects are + bracket-encoded form fields, e.g. `to[firstName]`); use this content type to + upload the PDF file directly. Args: back_template: The template ID for the back of the postcard. You can supply _either_ this or @@ -1217,22 +1260,25 @@ async def create( ] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Postcard: + ) -> PostcardCreateResponse: """Create a postcard. Note that you can supply one of the following: - HTML content for the front and back of the postcard - A template ID for the front and back of the postcard - - A URL or file for a 2 page PDF where the first page is the front of the - postcard and the second page is the back - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the front of the postcard and + the second page is the back Create a postcard via a multipart/form-data + request. Accepts the same fields as the JSON create body (nested objects are + bracket-encoded form fields, e.g. `to[firstName]`); use this content type to + upload the PDF file directly. Args: pdf: A URL pointing to a 2 page PDF file. The first page is the front of the postcard @@ -1293,7 +1339,7 @@ async def create( async def create( self, *, - pdf: Union[str, Base64FileInput], + pdf: FileTypes, size: Literal["6x4", "9x6", "11x6"], to: postcard_create_params.PostcardCreateWithPdfFileTo, description: str | Omit = omit, @@ -1341,26 +1387,30 @@ async def create( ] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Postcard: + ) -> PostcardCreateResponse: """Create a postcard. Note that you can supply one of the following: - HTML content for the front and back of the postcard - A template ID for the front and back of the postcard - - A URL or file for a 2 page PDF where the first page is the front of the - postcard and the second page is the back - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the front of the postcard and + the second page is the back Create a postcard via a multipart/form-data + request. Accepts the same fields as the JSON create body (nested objects are + bracket-encoded form fields, e.g. `to[firstName]`); use this content type to + upload the PDF file directly. Args: - pdf: A 2 page PDF file. The first page is the front of the postcard and the second - page is the back (where the address will be stamped on). + pdf: Represents a raw file upload. Sending the actual file requires a + `multipart/form-data` request; in `application/json` request bodies, supply a + URL instead. size: Enum representing the supported postcard sizes. @@ -1477,41 +1527,56 @@ async def create( ] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, back_template: str | Omit = omit, front_template: str | Omit = omit, - pdf: str | Union[str, Base64FileInput] | Omit = omit, + pdf: str | FileTypes | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> Postcard: - return await self._post( - "/print-mail/v1/postcards", - body=await async_maybe_transform( - { - "back_html": back_html, - "front_html": front_html, - "size": size, - "to": to, - "description": description, - "from_": from_, - "mailing_class": mailing_class, - "merge_variables": merge_variables, - "metadata": metadata, - "paper": paper, - "send_date": send_date, - "back_template": back_template, - "front_template": front_template, - "pdf": pdf, - }, - postcard_create_params.PostcardCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ) -> PostcardCreateResponse: + extra_headers = {**strip_not_given({"idempotency-key": idempotency_key}), **(extra_headers or {})} + body = deepcopy_with_paths( + { + "back_html": back_html, + "front_html": front_html, + "size": size, + "to": to, + "description": description, + "from_": from_, + "mailing_class": mailing_class, + "merge_variables": merge_variables, + "metadata": metadata, + "paper": paper, + "send_date": send_date, + "back_template": back_template, + "front_template": front_template, + "pdf": pdf, + }, + [["pdf"]], + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["pdf"]]) + if files: + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return cast( + PostcardCreateResponse, + await self._post( + "/print-mail/v1/postcards", + body=await async_maybe_transform(body, postcard_create_params.PostcardCreateParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, PostcardCreateResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=Postcard, ) async def retrieve( diff --git a/src/postgrid/resources/print_mail/self_mailers.py b/src/postgrid/resources/print_mail/self_mailers.py index 92fb5e0..5abfacf 100644 --- a/src/postgrid/resources/print_mail/self_mailers.py +++ b/src/postgrid/resources/print_mail/self_mailers.py @@ -2,14 +2,22 @@ from __future__ import annotations -from typing import Dict, Union +from typing import Any, Dict, Union, Mapping, cast from datetime import datetime from typing_extensions import Literal, overload import httpx -from ..._types import Body, Omit, Query, Headers, NotGiven, Base64FileInput, omit, not_given -from ..._utils import path_template, required_args, maybe_transform, async_maybe_transform +from ..._files import deepcopy_with_paths +from ..._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given +from ..._utils import ( + extract_files, + path_template, + required_args, + maybe_transform, + strip_not_given, + async_maybe_transform, +) from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -22,6 +30,7 @@ from ..._base_client import AsyncPaginator, make_request_options from ...types.print_mail import self_mailer_list_params, self_mailer_create_params from ...types.print_mail.self_mailer import SelfMailer +from ...types.print_mail.self_mailer_create_response import SelfMailerCreateResponse from ...types.print_mail.self_mailer_retrieve_url_response import SelfMailerRetrieveURLResponse __all__ = ["SelfMailersResource", "AsyncSelfMailersResource"] @@ -91,22 +100,25 @@ def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SelfMailer: + ) -> SelfMailerCreateResponse: """Create a self-mailer. Note that you can supply one of the following: - HTML content for the inside and outside of the self-mailer - A template ID for the inside and outside of the self-mailer - - A URL or file for a 2 page PDF where the first page is the outside of the - self-mailer and the second page is the inside - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the outside of the self-mailer + and the second page is the inside Create a self-mailer via a + multipart/form-data request. Accepts the same fields as the JSON create body + (nested objects are bracket-encoded form fields, e.g. `to[firstName]`); use + this content type to upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -193,22 +205,25 @@ def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SelfMailer: + ) -> SelfMailerCreateResponse: """Create a self-mailer. Note that you can supply one of the following: - HTML content for the inside and outside of the self-mailer - A template ID for the inside and outside of the self-mailer - - A URL or file for a 2 page PDF where the first page is the outside of the - self-mailer and the second page is the inside - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the outside of the self-mailer + and the second page is the inside Create a self-mailer via a + multipart/form-data request. Accepts the same fields as the JSON create body + (nested objects are bracket-encoded form fields, e.g. `to[firstName]`); use + this content type to upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -294,22 +309,25 @@ def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SelfMailer: + ) -> SelfMailerCreateResponse: """Create a self-mailer. Note that you can supply one of the following: - HTML content for the inside and outside of the self-mailer - A template ID for the inside and outside of the self-mailer - - A URL or file for a 2 page PDF where the first page is the outside of the - self-mailer and the second page is the inside - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the outside of the self-mailer + and the second page is the inside Create a self-mailer via a + multipart/form-data request. Accepts the same fields as the JSON create body + (nested objects are bracket-encoded form fields, e.g. `to[firstName]`); use + this content type to upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -357,7 +375,7 @@ def create( self, *, from_: self_mailer_create_params.SelfMailerCreateWithPdfFileFrom, - pdf: Union[str, Base64FileInput], + pdf: FileTypes, size: Literal["8.5x11_bifold", "8.5x11_trifold", "9.5x16_trifold"], to: self_mailer_create_params.SelfMailerCreateWithPdfFileTo, description: str | Omit = omit, @@ -393,29 +411,33 @@ def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SelfMailer: + ) -> SelfMailerCreateResponse: """Create a self-mailer. Note that you can supply one of the following: - HTML content for the inside and outside of the self-mailer - A template ID for the inside and outside of the self-mailer - - A URL or file for a 2 page PDF where the first page is the outside of the - self-mailer and the second page is the inside - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the outside of the self-mailer + and the second page is the inside Create a self-mailer via a + multipart/form-data request. Accepts the same fields as the JSON create body + (nested objects are bracket-encoded form fields, e.g. `to[firstName]`); use + this content type to upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline here just like you can for the `to`. - pdf: A 2 page PDF file. The first page is the inside of the self-mailer and the - second page is the outside (where the address will be stamped on). + pdf: Represents a raw file upload. Sending the actual file requires a + `multipart/form-data` request; in `application/json` request bodies, supply a + URL instead. size: Enum representing the supported self-mailer sizes. @@ -502,40 +524,55 @@ def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, inside_template: str | Omit = omit, outside_template: str | Omit = omit, - pdf: str | Union[str, Base64FileInput] | Omit = omit, + pdf: str | FileTypes | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SelfMailer: - return self._post( - "/print-mail/v1/self_mailers", - body=maybe_transform( - { - "from_": from_, - "inside_html": inside_html, - "outside_html": outside_html, - "size": size, - "to": to, - "description": description, - "mailing_class": mailing_class, - "merge_variables": merge_variables, - "metadata": metadata, - "send_date": send_date, - "inside_template": inside_template, - "outside_template": outside_template, - "pdf": pdf, - }, - self_mailer_create_params.SelfMailerCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ) -> SelfMailerCreateResponse: + extra_headers = {**strip_not_given({"idempotency-key": idempotency_key}), **(extra_headers or {})} + body = deepcopy_with_paths( + { + "from_": from_, + "inside_html": inside_html, + "outside_html": outside_html, + "size": size, + "to": to, + "description": description, + "mailing_class": mailing_class, + "merge_variables": merge_variables, + "metadata": metadata, + "send_date": send_date, + "inside_template": inside_template, + "outside_template": outside_template, + "pdf": pdf, + }, + [["pdf"]], + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["pdf"]]) + if files: + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return cast( + SelfMailerCreateResponse, + self._post( + "/print-mail/v1/self_mailers", + body=maybe_transform(body, self_mailer_create_params.SelfMailerCreateParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, SelfMailerCreateResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=SelfMailer, ) def retrieve( @@ -798,22 +835,25 @@ async def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SelfMailer: + ) -> SelfMailerCreateResponse: """Create a self-mailer. Note that you can supply one of the following: - HTML content for the inside and outside of the self-mailer - A template ID for the inside and outside of the self-mailer - - A URL or file for a 2 page PDF where the first page is the outside of the - self-mailer and the second page is the inside - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the outside of the self-mailer + and the second page is the inside Create a self-mailer via a + multipart/form-data request. Accepts the same fields as the JSON create body + (nested objects are bracket-encoded form fields, e.g. `to[firstName]`); use + this content type to upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -900,22 +940,25 @@ async def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SelfMailer: + ) -> SelfMailerCreateResponse: """Create a self-mailer. Note that you can supply one of the following: - HTML content for the inside and outside of the self-mailer - A template ID for the inside and outside of the self-mailer - - A URL or file for a 2 page PDF where the first page is the outside of the - self-mailer and the second page is the inside - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the outside of the self-mailer + and the second page is the inside Create a self-mailer via a + multipart/form-data request. Accepts the same fields as the JSON create body + (nested objects are bracket-encoded form fields, e.g. `to[firstName]`); use + this content type to upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -1001,22 +1044,25 @@ async def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SelfMailer: + ) -> SelfMailerCreateResponse: """Create a self-mailer. Note that you can supply one of the following: - HTML content for the inside and outside of the self-mailer - A template ID for the inside and outside of the self-mailer - - A URL or file for a 2 page PDF where the first page is the outside of the - self-mailer and the second page is the inside - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the outside of the self-mailer + and the second page is the inside Create a self-mailer via a + multipart/form-data request. Accepts the same fields as the JSON create body + (nested objects are bracket-encoded form fields, e.g. `to[firstName]`); use + this content type to upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -1064,7 +1110,7 @@ async def create( self, *, from_: self_mailer_create_params.SelfMailerCreateWithPdfFileFrom, - pdf: Union[str, Base64FileInput], + pdf: FileTypes, size: Literal["8.5x11_bifold", "8.5x11_trifold", "9.5x16_trifold"], to: self_mailer_create_params.SelfMailerCreateWithPdfFileTo, description: str | Omit = omit, @@ -1100,29 +1146,33 @@ async def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SelfMailer: + ) -> SelfMailerCreateResponse: """Create a self-mailer. Note that you can supply one of the following: - HTML content for the inside and outside of the self-mailer - A template ID for the inside and outside of the self-mailer - - A URL or file for a 2 page PDF where the first page is the outside of the - self-mailer and the second page is the inside - - Upload the aforementioned PDF file via a multipart form upload request + - A URL for a 2 page PDF where the first page is the outside of the self-mailer + and the second page is the inside Create a self-mailer via a + multipart/form-data request. Accepts the same fields as the JSON create body + (nested objects are bracket-encoded form fields, e.g. `to[firstName]`); use + this content type to upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline here just like you can for the `to`. - pdf: A 2 page PDF file. The first page is the inside of the self-mailer and the - second page is the outside (where the address will be stamped on). + pdf: Represents a raw file upload. Sending the actual file requires a + `multipart/form-data` request; in `application/json` request bodies, supply a + URL instead. size: Enum representing the supported self-mailer sizes. @@ -1209,40 +1259,55 @@ async def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, inside_template: str | Omit = omit, outside_template: str | Omit = omit, - pdf: str | Union[str, Base64FileInput] | Omit = omit, + pdf: str | FileTypes | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SelfMailer: - return await self._post( - "/print-mail/v1/self_mailers", - body=await async_maybe_transform( - { - "from_": from_, - "inside_html": inside_html, - "outside_html": outside_html, - "size": size, - "to": to, - "description": description, - "mailing_class": mailing_class, - "merge_variables": merge_variables, - "metadata": metadata, - "send_date": send_date, - "inside_template": inside_template, - "outside_template": outside_template, - "pdf": pdf, - }, - self_mailer_create_params.SelfMailerCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ) -> SelfMailerCreateResponse: + extra_headers = {**strip_not_given({"idempotency-key": idempotency_key}), **(extra_headers or {})} + body = deepcopy_with_paths( + { + "from_": from_, + "inside_html": inside_html, + "outside_html": outside_html, + "size": size, + "to": to, + "description": description, + "mailing_class": mailing_class, + "merge_variables": merge_variables, + "metadata": metadata, + "send_date": send_date, + "inside_template": inside_template, + "outside_template": outside_template, + "pdf": pdf, + }, + [["pdf"]], + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["pdf"]]) + if files: + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return cast( + SelfMailerCreateResponse, + await self._post( + "/print-mail/v1/self_mailers", + body=await async_maybe_transform(body, self_mailer_create_params.SelfMailerCreateParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, SelfMailerCreateResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=SelfMailer, ) async def retrieve( diff --git a/src/postgrid/resources/print_mail/snap_packs.py b/src/postgrid/resources/print_mail/snap_packs.py index 29dec0f..3f91088 100644 --- a/src/postgrid/resources/print_mail/snap_packs.py +++ b/src/postgrid/resources/print_mail/snap_packs.py @@ -2,14 +2,22 @@ from __future__ import annotations -from typing import Dict, Union +from typing import Any, Dict, Union, Mapping, cast from datetime import datetime from typing_extensions import Literal, overload import httpx -from ..._types import Body, Omit, Query, Headers, NotGiven, omit, not_given -from ..._utils import path_template, required_args, maybe_transform, async_maybe_transform +from ..._files import deepcopy_with_paths +from ..._types import Body, Omit, Query, Headers, NotGiven, FileTypes, omit, not_given +from ..._utils import ( + extract_files, + path_template, + required_args, + maybe_transform, + strip_not_given, + async_maybe_transform, +) from ..._compat import cached_property from ..._resource import SyncAPIResource, AsyncAPIResource from ..._response import ( @@ -21,11 +29,8 @@ from ...pagination import SyncSkipLimit, AsyncSkipLimit from ..._base_client import AsyncPaginator, make_request_options from ...types.print_mail import snap_pack_list_params, snap_pack_create_params, snap_pack_retrieve_capabilities_params -from ...types.print_mail.snap_pack_list_response import SnapPackListResponse +from ...types.print_mail.snap_pack import SnapPack from ...types.print_mail.snap_pack_create_response import SnapPackCreateResponse -from ...types.print_mail.snap_pack_delete_response import SnapPackDeleteResponse -from ...types.print_mail.snap_pack_retrieve_response import SnapPackRetrieveResponse -from ...types.print_mail.snap_pack_progressions_response import SnapPackProgressionsResponse from ...types.print_mail.snap_pack_retrieve_capabilities_response import SnapPackRetrieveCapabilitiesResponse __all__ = ["SnapPacksResource", "AsyncSnapPacksResource"] @@ -104,6 +109,7 @@ def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -117,7 +123,10 @@ def create( - HTML content for the inside and outside of the snap pack - Template IDs for the inside and outside of the snap pack - - A URL or file upload for a two-page PDF that matches the snap pack layout + - A URL for a two-page PDF that matches the snap pack layout Create a snap pack + via a multipart/form-data request. Accepts the same fields as the JSON create + body (nested objects are bracket-encoded form fields, e.g. `to[firstName]`); + use this content type to upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -204,6 +213,7 @@ def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -217,7 +227,10 @@ def create( - HTML content for the inside and outside of the snap pack - Template IDs for the inside and outside of the snap pack - - A URL or file upload for a two-page PDF that matches the snap pack layout + - A URL for a two-page PDF that matches the snap pack layout Create a snap pack + via a multipart/form-data request. Accepts the same fields as the JSON create + body (nested objects are bracket-encoded form fields, e.g. `to[firstName]`); + use this content type to upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -267,7 +280,7 @@ def create( self, *, from_: snap_pack_create_params.SnapPackCreateWithPdfFrom, - pdf: str, + pdf: Union[str, FileTypes], size: Literal["8.5x11_bifold_v"], to: snap_pack_create_params.SnapPackCreateWithPdfTo, description: str | Omit = omit, @@ -303,6 +316,7 @@ def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -316,7 +330,10 @@ def create( - HTML content for the inside and outside of the snap pack - Template IDs for the inside and outside of the snap pack - - A URL or file upload for a two-page PDF that matches the snap pack layout + - A URL for a two-page PDF that matches the snap pack layout Create a snap pack + via a multipart/form-data request. Accepts the same fields as the JSON create + body (nested objects are bracket-encoded form fields, e.g. `to[firstName]`); + use this content type to upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -408,9 +425,10 @@ def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, inside_template: str | Omit = omit, outside_template: str | Omit = omit, - pdf: str | Omit = omit, + pdf: Union[str, FileTypes] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -418,30 +436,44 @@ def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SnapPackCreateResponse: - return self._post( - "/print-mail/v1/snap_packs", - body=maybe_transform( - { - "from_": from_, - "inside_html": inside_html, - "outside_html": outside_html, - "size": size, - "to": to, - "description": description, - "mailing_class": mailing_class, - "merge_variables": merge_variables, - "metadata": metadata, - "send_date": send_date, - "inside_template": inside_template, - "outside_template": outside_template, - "pdf": pdf, - }, - snap_pack_create_params.SnapPackCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers = {**strip_not_given({"idempotency-key": idempotency_key}), **(extra_headers or {})} + body = deepcopy_with_paths( + { + "from_": from_, + "inside_html": inside_html, + "outside_html": outside_html, + "size": size, + "to": to, + "description": description, + "mailing_class": mailing_class, + "merge_variables": merge_variables, + "metadata": metadata, + "send_date": send_date, + "inside_template": inside_template, + "outside_template": outside_template, + "pdf": pdf, + }, + [["pdf"]], + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["pdf"]]) + if files: + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return cast( + SnapPackCreateResponse, + self._post( + "/print-mail/v1/snap_packs", + body=maybe_transform(body, snap_pack_create_params.SnapPackCreateParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, SnapPackCreateResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=SnapPackCreateResponse, ) def retrieve( @@ -454,7 +486,7 @@ def retrieve( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SnapPackRetrieveResponse: + ) -> SnapPack: """ Retrieve a snap pack by ID. @@ -474,7 +506,7 @@ def retrieve( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=SnapPackRetrieveResponse, + cast_to=SnapPack, ) def list( @@ -489,7 +521,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SyncSkipLimit[SnapPackListResponse]: + ) -> SyncSkipLimit[SnapPack]: """ Get a list of snap packs. @@ -510,7 +542,7 @@ def list( """ return self._get_api_list( "/print-mail/v1/snap_packs", - page=SyncSkipLimit[SnapPackListResponse], + page=SyncSkipLimit[SnapPack], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -525,7 +557,7 @@ def list( snap_pack_list_params.SnapPackListParams, ), ), - model=SnapPackListResponse, + model=SnapPack, ) def delete( @@ -538,7 +570,7 @@ def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SnapPackDeleteResponse: + ) -> SnapPack: """Cancel a snap pack by ID. Note that this operation cannot be undone and that @@ -560,7 +592,7 @@ def delete( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=SnapPackDeleteResponse, + cast_to=SnapPack, ) def progressions( @@ -573,7 +605,7 @@ def progressions( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SnapPackProgressionsResponse: + ) -> SnapPack: """Progresses a snap pack's `status` to the next stage. This is only available in @@ -599,7 +631,7 @@ def progressions( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=SnapPackProgressionsResponse, + cast_to=SnapPack, ) def retrieve_capabilities( @@ -728,6 +760,7 @@ async def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -741,7 +774,10 @@ async def create( - HTML content for the inside and outside of the snap pack - Template IDs for the inside and outside of the snap pack - - A URL or file upload for a two-page PDF that matches the snap pack layout + - A URL for a two-page PDF that matches the snap pack layout Create a snap pack + via a multipart/form-data request. Accepts the same fields as the JSON create + body (nested objects are bracket-encoded form fields, e.g. `to[firstName]`); + use this content type to upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -828,6 +864,7 @@ async def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -841,7 +878,10 @@ async def create( - HTML content for the inside and outside of the snap pack - Template IDs for the inside and outside of the snap pack - - A URL or file upload for a two-page PDF that matches the snap pack layout + - A URL for a two-page PDF that matches the snap pack layout Create a snap pack + via a multipart/form-data request. Accepts the same fields as the JSON create + body (nested objects are bracket-encoded form fields, e.g. `to[firstName]`); + use this content type to upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -891,7 +931,7 @@ async def create( self, *, from_: snap_pack_create_params.SnapPackCreateWithPdfFrom, - pdf: str, + pdf: Union[str, FileTypes], size: Literal["8.5x11_bifold_v"], to: snap_pack_create_params.SnapPackCreateWithPdfTo, description: str | Omit = omit, @@ -927,6 +967,7 @@ async def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -940,7 +981,10 @@ async def create( - HTML content for the inside and outside of the snap pack - Template IDs for the inside and outside of the snap pack - - A URL or file upload for a two-page PDF that matches the snap pack layout + - A URL for a two-page PDF that matches the snap pack layout Create a snap pack + via a multipart/form-data request. Accepts the same fields as the JSON create + body (nested objects are bracket-encoded form fields, e.g. `to[firstName]`); + use this content type to upload the PDF file directly. Args: from_: The contact information of the sender. You can pass contact information inline @@ -1032,9 +1076,10 @@ async def create( merge_variables: Dict[str, object] | Omit = omit, metadata: Dict[str, object] | Omit = omit, send_date: Union[str, datetime] | Omit = omit, + idempotency_key: str | Omit = omit, inside_template: str | Omit = omit, outside_template: str | Omit = omit, - pdf: str | Omit = omit, + pdf: Union[str, FileTypes] | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -1042,30 +1087,44 @@ async def create( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> SnapPackCreateResponse: - return await self._post( - "/print-mail/v1/snap_packs", - body=await async_maybe_transform( - { - "from_": from_, - "inside_html": inside_html, - "outside_html": outside_html, - "size": size, - "to": to, - "description": description, - "mailing_class": mailing_class, - "merge_variables": merge_variables, - "metadata": metadata, - "send_date": send_date, - "inside_template": inside_template, - "outside_template": outside_template, - "pdf": pdf, - }, - snap_pack_create_params.SnapPackCreateParams, - ), - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + extra_headers = {**strip_not_given({"idempotency-key": idempotency_key}), **(extra_headers or {})} + body = deepcopy_with_paths( + { + "from_": from_, + "inside_html": inside_html, + "outside_html": outside_html, + "size": size, + "to": to, + "description": description, + "mailing_class": mailing_class, + "merge_variables": merge_variables, + "metadata": metadata, + "send_date": send_date, + "inside_template": inside_template, + "outside_template": outside_template, + "pdf": pdf, + }, + [["pdf"]], + ) + files = extract_files(cast(Mapping[str, object], body), paths=[["pdf"]]) + if files: + # It should be noted that the actual Content-Type header that will be + # sent to the server will contain a `boundary` parameter, e.g. + # multipart/form-data; boundary=---abc-- + extra_headers = {"Content-Type": "multipart/form-data", **(extra_headers or {})} + return cast( + SnapPackCreateResponse, + await self._post( + "/print-mail/v1/snap_packs", + body=await async_maybe_transform(body, snap_pack_create_params.SnapPackCreateParams), + files=files, + options=make_request_options( + extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout + ), + cast_to=cast( + Any, SnapPackCreateResponse + ), # Union types cannot be passed in as arguments in the type system ), - cast_to=SnapPackCreateResponse, ) async def retrieve( @@ -1078,7 +1137,7 @@ async def retrieve( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SnapPackRetrieveResponse: + ) -> SnapPack: """ Retrieve a snap pack by ID. @@ -1098,7 +1157,7 @@ async def retrieve( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=SnapPackRetrieveResponse, + cast_to=SnapPack, ) def list( @@ -1113,7 +1172,7 @@ def list( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> AsyncPaginator[SnapPackListResponse, AsyncSkipLimit[SnapPackListResponse]]: + ) -> AsyncPaginator[SnapPack, AsyncSkipLimit[SnapPack]]: """ Get a list of snap packs. @@ -1134,7 +1193,7 @@ def list( """ return self._get_api_list( "/print-mail/v1/snap_packs", - page=AsyncSkipLimit[SnapPackListResponse], + page=AsyncSkipLimit[SnapPack], options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, @@ -1149,7 +1208,7 @@ def list( snap_pack_list_params.SnapPackListParams, ), ), - model=SnapPackListResponse, + model=SnapPack, ) async def delete( @@ -1162,7 +1221,7 @@ async def delete( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SnapPackDeleteResponse: + ) -> SnapPack: """Cancel a snap pack by ID. Note that this operation cannot be undone and that @@ -1184,7 +1243,7 @@ async def delete( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=SnapPackDeleteResponse, + cast_to=SnapPack, ) async def progressions( @@ -1197,7 +1256,7 @@ async def progressions( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, - ) -> SnapPackProgressionsResponse: + ) -> SnapPack: """Progresses a snap pack's `status` to the next stage. This is only available in @@ -1223,7 +1282,7 @@ async def progressions( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=SnapPackProgressionsResponse, + cast_to=SnapPack, ) async def retrieve_capabilities( diff --git a/src/postgrid/types/print_mail/__init__.py b/src/postgrid/types/print_mail/__init__.py index f71b44c..0f252b8 100644 --- a/src/postgrid/types/print_mail/__init__.py +++ b/src/postgrid/types/print_mail/__init__.py @@ -12,6 +12,7 @@ from .postcard import Postcard as Postcard from .template import Template as Template from .file_type import FileType as FileType +from .snap_pack import SnapPack as SnapPack from .cheque_size import ChequeSize as ChequeSize from .letter_size import LetterSize as LetterSize from .self_mailer import SelfMailer as SelfMailer @@ -64,6 +65,7 @@ from .webhook_update_params import WebhookUpdateParams as WebhookUpdateParams from .campaign_create_params import CampaignCreateParams as CampaignCreateParams from .campaign_update_params import CampaignUpdateParams as CampaignUpdateParams +from .letter_create_response import LetterCreateResponse as LetterCreateResponse from .postcard_cancel_params import PostcardCancelParams as PostcardCancelParams from .postcard_create_params import PostcardCreateParams as PostcardCreateParams from .template_create_params import TemplateCreateParams as TemplateCreateParams @@ -71,7 +73,6 @@ from .contact_delete_response import ContactDeleteResponse as ContactDeleteResponse from .self_mailer_list_params import SelfMailerListParams as SelfMailerListParams from .snap_pack_create_params import SnapPackCreateParams as SnapPackCreateParams -from .snap_pack_list_response import SnapPackListResponse as SnapPackListResponse from .tracker_create_response import TrackerCreateResponse as TrackerCreateResponse from .tracker_delete_response import TrackerDeleteResponse as TrackerDeleteResponse from .tracker_update_response import TrackerUpdateResponse as TrackerUpdateResponse @@ -80,19 +81,19 @@ from .campaign_delete_response import CampaignDeleteResponse as CampaignDeleteResponse from .mailing_list_jobs_params import MailingListJobsParams as MailingListJobsParams from .mailing_list_list_params import MailingListListParams as MailingListListParams +from .postcard_create_response import PostcardCreateResponse as PostcardCreateResponse from .template_delete_response import TemplateDeleteResponse as TemplateDeleteResponse from .bank_account_country_code import BankAccountCountryCode as BankAccountCountryCode from .box_progressions_response import BoxProgressionsResponse as BoxProgressionsResponse from .self_mailer_create_params import SelfMailerCreateParams as SelfMailerCreateParams from .snap_pack_create_response import SnapPackCreateResponse as SnapPackCreateResponse -from .snap_pack_delete_response import SnapPackDeleteResponse as SnapPackDeleteResponse from .tracker_retrieve_response import TrackerRetrieveResponse as TrackerRetrieveResponse from .verification_status_count import VerificationStatusCount as VerificationStatusCount from .bank_account_create_params import BankAccountCreateParams as BankAccountCreateParams from .mailing_list_create_params import MailingListCreateParams as MailingListCreateParams from .mailing_list_update_params import MailingListUpdateParams as MailingListUpdateParams from .return_envelope_list_params import ReturnEnvelopeListParams as ReturnEnvelopeListParams -from .snap_pack_retrieve_response import SnapPackRetrieveResponse as SnapPackRetrieveResponse +from .self_mailer_create_response import SelfMailerCreateResponse as SelfMailerCreateResponse from .virtual_mailbox_list_params import VirtualMailboxListParams as VirtualMailboxListParams from .bank_account_delete_response import BankAccountDeleteResponse as BankAccountDeleteResponse from .cheque_retrieve_url_response import ChequeRetrieveURLResponse as ChequeRetrieveURLResponse @@ -107,7 +108,6 @@ from .sub_organization_create_params import SubOrganizationCreateParams as SubOrganizationCreateParams from .tracker_retrieve_visits_params import TrackerRetrieveVisitsParams as TrackerRetrieveVisitsParams from .mailing_list_import_list_params import MailingListImportListParams as MailingListImportListParams -from .snap_pack_progressions_response import SnapPackProgressionsResponse as SnapPackProgressionsResponse from .targeted_list_build_list_params import TargetedListBuildListParams as TargetedListBuildListParams from .virtual_mailbox_create_response import VirtualMailboxCreateResponse as VirtualMailboxCreateResponse from .webhook_list_invocations_params import WebhookListInvocationsParams as WebhookListInvocationsParams diff --git a/src/postgrid/types/print_mail/attached_pdf.py b/src/postgrid/types/print_mail/attached_pdf.py index 03a7e71..6aa6da6 100644 --- a/src/postgrid/types/print_mail/attached_pdf.py +++ b/src/postgrid/types/print_mail/attached_pdf.py @@ -1,5 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +from typing import Union from typing_extensions import Literal from ..._models import BaseModel @@ -10,7 +11,7 @@ class AttachedPdf(BaseModel): """Model representing an attached PDF.""" - file: str + file: Union[str, object] """The file (multipart form upload) or URL pointing to a PDF for the attached PDF.""" placement: Literal["before_template", "after_template"] diff --git a/src/postgrid/types/print_mail/attached_pdf_param.py b/src/postgrid/types/print_mail/attached_pdf_param.py index 3f23c1d..ccde307 100644 --- a/src/postgrid/types/print_mail/attached_pdf_param.py +++ b/src/postgrid/types/print_mail/attached_pdf_param.py @@ -2,15 +2,18 @@ from __future__ import annotations +from typing import Union from typing_extensions import Literal, Required, TypedDict +from ..._types import FileTypes + __all__ = ["AttachedPdfParam"] class AttachedPdfParam(TypedDict, total=False): """Model representing an attached PDF.""" - file: Required[str] + file: Required[Union[str, FileTypes]] """The file (multipart form upload) or URL pointing to a PDF for the attached PDF.""" placement: Required[Literal["before_template", "after_template"]] diff --git a/src/postgrid/types/print_mail/campaign_create_params.py b/src/postgrid/types/print_mail/campaign_create_params.py index d711cad..c7eaa9f 100644 --- a/src/postgrid/types/print_mail/campaign_create_params.py +++ b/src/postgrid/types/print_mail/campaign_create_params.py @@ -6,9 +6,8 @@ from datetime import datetime from typing_extensions import Literal, Required, Annotated, TypedDict -from ..._types import Base64FileInput +from ..._types import FileTypes from ..._utils import PropertyInfo -from ..._models import set_pydantic_config from .cheque_size import ChequeSize from .letter_size import LetterSize from .address_placement import AddressPlacement @@ -102,7 +101,7 @@ class Cheque(TypedDict, total=False): envelope: str """The custom envelope ID or `"standard"`.""" - letter_pdf: Annotated[Union[str, Base64FileInput], PropertyInfo(alias="letterPDF", format="base64")] + letter_pdf: Annotated[Union[str, FileTypes], PropertyInfo(alias="letterPDF")] """PDF file for an optional attached letter. Cannot be used with `letterTemplate`.""" letter_settings: Annotated[ChequeLetterSettings, PropertyInfo(alias="letterSettings")] @@ -169,9 +168,6 @@ class Cheque(TypedDict, total=False): """Enum representing the supported cheque sizes.""" -set_pydantic_config(Cheque, {"arbitrary_types_allowed": True}) - - class Letter(TypedDict, total=False): """Inline letter configuration for a campaign. @@ -246,7 +242,7 @@ class Letter(TypedDict, total=False): If omitted, org default is used when configured; otherwise "standard". """ - pdf: str + pdf: Union[str, FileTypes] """A PDF file or URL for the letter content. Cannot be used with `template`.""" perforated_page: Annotated[Literal[1], PropertyInfo(alias="perforatedPage")] @@ -331,7 +327,7 @@ class Postcard(TypedDict, total=False): If omitted, org default is used when configured; otherwise "standard". """ - pdf: str + pdf: Union[str, FileTypes] """A 2-page PDF file for the postcard content (front and back). Cannot be used with `frontTemplate`/`backTemplate`. @@ -395,7 +391,7 @@ class SelfMailer(TypedDict, total=False): outside_template: Annotated[str, PropertyInfo(alias="outsideTemplate")] """ID of the template for the outside. Cannot be used with `pdf`.""" - pdf: str + pdf: Union[str, FileTypes] """A 2-page PDF file for the self-mailer content. Cannot be used with `insideTemplate`/`outsideTemplate`. @@ -459,7 +455,7 @@ class SnapPack(TypedDict, total=False): outside_template: Annotated[str, PropertyInfo(alias="outsideTemplate")] """ID of the template for the outside. Cannot be used with `pdf`.""" - pdf: str + pdf: Union[str, FileTypes] """A 2-page PDF file for the snap pack content. Cannot be used with `insideTemplate`/`outsideTemplate`. diff --git a/src/postgrid/types/print_mail/campaign_update_params.py b/src/postgrid/types/print_mail/campaign_update_params.py index 25af9a0..5e9cf70 100644 --- a/src/postgrid/types/print_mail/campaign_update_params.py +++ b/src/postgrid/types/print_mail/campaign_update_params.py @@ -5,9 +5,8 @@ from typing import Dict, Union, Optional from typing_extensions import Literal, Annotated, TypedDict -from ..._types import Base64FileInput +from ..._types import FileTypes from ..._utils import PropertyInfo -from ..._models import set_pydantic_config from .cheque_size import ChequeSize from .letter_size import LetterSize from .address_placement import AddressPlacement @@ -96,7 +95,7 @@ class Cheque(TypedDict, total=False): envelope: str """The custom envelope ID or `"standard"`.""" - letter_pdf: Annotated[Union[str, Base64FileInput], PropertyInfo(alias="letterPDF", format="base64")] + letter_pdf: Annotated[Union[str, FileTypes], PropertyInfo(alias="letterPDF")] """PDF file for an optional attached letter. Cannot be used with `letterTemplate`.""" letter_settings: Annotated[ChequeLetterSettings, PropertyInfo(alias="letterSettings")] @@ -163,9 +162,6 @@ class Cheque(TypedDict, total=False): """Enum representing the supported cheque sizes.""" -set_pydantic_config(Cheque, {"arbitrary_types_allowed": True}) - - class Letter(TypedDict, total=False): """Inline letter configuration for a campaign. @@ -240,7 +236,7 @@ class Letter(TypedDict, total=False): If omitted, org default is used when configured; otherwise "standard". """ - pdf: str + pdf: Union[str, FileTypes] """A PDF file or URL for the letter content. Cannot be used with `template`.""" perforated_page: Annotated[Literal[1], PropertyInfo(alias="perforatedPage")] @@ -325,7 +321,7 @@ class Postcard(TypedDict, total=False): If omitted, org default is used when configured; otherwise "standard". """ - pdf: str + pdf: Union[str, FileTypes] """A 2-page PDF file for the postcard content (front and back). Cannot be used with `frontTemplate`/`backTemplate`. @@ -389,7 +385,7 @@ class SelfMailer(TypedDict, total=False): outside_template: Annotated[str, PropertyInfo(alias="outsideTemplate")] """ID of the template for the outside. Cannot be used with `pdf`.""" - pdf: str + pdf: Union[str, FileTypes] """A 2-page PDF file for the self-mailer content. Cannot be used with `insideTemplate`/`outsideTemplate`. @@ -453,7 +449,7 @@ class SnapPack(TypedDict, total=False): outside_template: Annotated[str, PropertyInfo(alias="outsideTemplate")] """ID of the template for the outside. Cannot be used with `pdf`.""" - pdf: str + pdf: Union[str, FileTypes] """A 2-page PDF file for the snap pack content. Cannot be used with `insideTemplate`/`outsideTemplate`. diff --git a/src/postgrid/types/print_mail/cheque_create_params.py b/src/postgrid/types/print_mail/cheque_create_params.py index d7cb6d8..94f6132 100644 --- a/src/postgrid/types/print_mail/cheque_create_params.py +++ b/src/postgrid/types/print_mail/cheque_create_params.py @@ -6,7 +6,7 @@ from datetime import datetime from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -from ..._types import Base64FileInput +from ..._types import FileTypes from ..._utils import PropertyInfo from .cheque_size import ChequeSize from .digital_only_param import DigitalOnlyParam @@ -71,7 +71,7 @@ class ChequeCreateParams(TypedDict, total=False): than one. """ - letter_pdf: Annotated[Union[str, Base64FileInput], PropertyInfo(alias="letterPDF", format="base64")] + letter_pdf: Annotated[Union[str, FileTypes], PropertyInfo(alias="letterPDF")] """ A URL pointing to a PDF for the letter attached to the cheque, or the PDF file itself when uploaded via a multipart form request. You can supply _either_ this, @@ -178,6 +178,8 @@ class ChequeCreateParams(TypedDict, total=False): size: ChequeSize """Enum representing the supported cheque sizes.""" + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + From: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] diff --git a/src/postgrid/types/print_mail/letter_create_params.py b/src/postgrid/types/print_mail/letter_create_params.py index 53b146f..b46b309 100644 --- a/src/postgrid/types/print_mail/letter_create_params.py +++ b/src/postgrid/types/print_mail/letter_create_params.py @@ -6,6 +6,7 @@ from datetime import datetime from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from ..._types import FileTypes from ..._utils import PropertyInfo from .letter_size import LetterSize from .address_placement import AddressPlacement @@ -158,6 +159,8 @@ class LetterCreateWithHTML(TypedDict, total=False): size: LetterSize """Enum representing the supported letter sizes.""" + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + LetterCreateWithHTMLFrom: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] @@ -294,6 +297,8 @@ class LetterCreateWithTemplate(TypedDict, total=False): size: LetterSize """Enum representing the supported letter sizes.""" + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + LetterCreateWithTemplateFrom: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] @@ -307,7 +312,7 @@ class LetterCreateWithPdf(TypedDict, total=False): You can pass contact information inline here just like you can for the `to`. """ - pdf: Required[str] + pdf: Required[Union[str, FileTypes]] """A URL pointing to a PDF file for the letter or the PDF file itself.""" to: Required[LetterCreateWithPdfTo] @@ -427,6 +432,8 @@ class LetterCreateWithPdf(TypedDict, total=False): size: LetterSize """Enum representing the supported letter sizes.""" + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + LetterCreateWithPdfFrom: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] diff --git a/src/postgrid/types/print_mail/letter_create_response.py b/src/postgrid/types/print_mail/letter_create_response.py new file mode 100644 index 0000000..02c2654 --- /dev/null +++ b/src/postgrid/types/print_mail/letter_create_response.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union +from typing_extensions import TypeAlias + +from .letter import Letter + +__all__ = ["LetterCreateResponse"] + +LetterCreateResponse: TypeAlias = Union[Letter, Letter] diff --git a/src/postgrid/types/print_mail/plastic_card.py b/src/postgrid/types/print_mail/plastic_card.py index a064411..ff1ad08 100644 --- a/src/postgrid/types/print_mail/plastic_card.py +++ b/src/postgrid/types/print_mail/plastic_card.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import Union, Optional from typing_extensions import Literal from pydantic import Field as FieldInfo @@ -25,7 +25,7 @@ class DoubleSided(BaseModel): front_template: Optional[str] = FieldInfo(alias="frontTemplate", default=None) """The template ID for the front side of the double-sided plastic card.""" - pdf: Optional[str] = None + pdf: Union[str, object, None] = None """ A URL pointing to a PDF file for the double-sided plastic card or the file itself. @@ -41,7 +41,7 @@ class SingleSided(BaseModel): Can specify one of this, `template`, or `pdf`. """ - pdf: Optional[str] = None + pdf: Union[str, object, None] = None """ A URL pointing to a PDF file for the single-sided plastic card or the PDF file itself. diff --git a/src/postgrid/types/print_mail/plastic_card_param.py b/src/postgrid/types/print_mail/plastic_card_param.py index 22f457b..97ddf65 100644 --- a/src/postgrid/types/print_mail/plastic_card_param.py +++ b/src/postgrid/types/print_mail/plastic_card_param.py @@ -2,8 +2,10 @@ from __future__ import annotations +from typing import Union from typing_extensions import Literal, Required, Annotated, TypedDict +from ..._types import FileTypes from ..._utils import PropertyInfo __all__ = ["PlasticCardParam", "DoubleSided", "SingleSided"] @@ -24,7 +26,7 @@ class DoubleSided(TypedDict, total=False): front_template: Annotated[str, PropertyInfo(alias="frontTemplate")] """The template ID for the front side of the double-sided plastic card.""" - pdf: str + pdf: Union[str, FileTypes] """ A URL pointing to a PDF file for the double-sided plastic card or the file itself. @@ -40,7 +42,7 @@ class SingleSided(TypedDict, total=False): Can specify one of this, `template`, or `pdf`. """ - pdf: str + pdf: Union[str, FileTypes] """ A URL pointing to a PDF file for the single-sided plastic card or the PDF file itself. diff --git a/src/postgrid/types/print_mail/postcard_create_params.py b/src/postgrid/types/print_mail/postcard_create_params.py index 247697b..f848530 100644 --- a/src/postgrid/types/print_mail/postcard_create_params.py +++ b/src/postgrid/types/print_mail/postcard_create_params.py @@ -6,7 +6,7 @@ from datetime import datetime from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -from ..._types import Base64FileInput +from ..._types import FileTypes from ..._utils import PropertyInfo from .contact_create_with_first_name_param import ContactCreateWithFirstNameParam from .contact_create_with_company_name_param import ContactCreateWithCompanyNameParam @@ -144,6 +144,8 @@ class PostcardCreateWithHTML(TypedDict, total=False): You can use this parameter to schedule orders for a future date. """ + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + PostcardCreateWithHTMLTo: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] @@ -266,6 +268,8 @@ class PostcardCreateWithTemplate(TypedDict, total=False): You can use this parameter to schedule orders for a future date. """ + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + PostcardCreateWithTemplateTo: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] @@ -385,6 +389,8 @@ class PostcardCreateWithPdfurl(TypedDict, total=False): You can use this parameter to schedule orders for a future date. """ + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + PostcardCreateWithPdfurlTo: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] @@ -392,11 +398,11 @@ class PostcardCreateWithPdfurl(TypedDict, total=False): class PostcardCreateWithPdfFile(TypedDict, total=False): - pdf: Required[Annotated[Union[str, Base64FileInput], PropertyInfo(format="base64")]] - """A 2 page PDF file. + pdf: Required[FileTypes] + """Represents a raw file upload. - The first page is the front of the postcard and the second page is the back - (where the address will be stamped on). + Sending the actual file requires a `multipart/form-data` request; in + `application/json` request bodies, supply a URL instead. """ size: Required[Literal["6x4", "9x6", "11x6"]] @@ -502,6 +508,8 @@ class PostcardCreateWithPdfFile(TypedDict, total=False): You can use this parameter to schedule orders for a future date. """ + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + PostcardCreateWithPdfFileTo: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] diff --git a/src/postgrid/types/print_mail/postcard_create_response.py b/src/postgrid/types/print_mail/postcard_create_response.py new file mode 100644 index 0000000..ab33fba --- /dev/null +++ b/src/postgrid/types/print_mail/postcard_create_response.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union +from typing_extensions import TypeAlias + +from .postcard import Postcard + +__all__ = ["PostcardCreateResponse"] + +PostcardCreateResponse: TypeAlias = Union[Postcard, Postcard] diff --git a/src/postgrid/types/print_mail/self_mailer_create_params.py b/src/postgrid/types/print_mail/self_mailer_create_params.py index 3aa282d..957e9f2 100644 --- a/src/postgrid/types/print_mail/self_mailer_create_params.py +++ b/src/postgrid/types/print_mail/self_mailer_create_params.py @@ -6,7 +6,7 @@ from datetime import datetime from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict -from ..._types import Base64FileInput +from ..._types import FileTypes from ..._utils import PropertyInfo from .contact_create_with_first_name_param import ContactCreateWithFirstNameParam from .contact_create_with_company_name_param import ContactCreateWithCompanyNameParam @@ -118,6 +118,8 @@ class SelfMailerCreateWithHTML(TypedDict, total=False): You can use this parameter to schedule orders for a future date. """ + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + SelfMailerCreateWithHTMLFrom: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] @@ -214,6 +216,8 @@ class SelfMailerCreateWithTemplate(TypedDict, total=False): You can use this parameter to schedule orders for a future date. """ + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + SelfMailerCreateWithTemplateFrom: TypeAlias = Union[ ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str @@ -309,6 +313,8 @@ class SelfMailerCreateWithPdfurl(TypedDict, total=False): You can use this parameter to schedule orders for a future date. """ + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + SelfMailerCreateWithPdfurlFrom: TypeAlias = Union[ ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str @@ -324,11 +330,11 @@ class SelfMailerCreateWithPdfFile(TypedDict, total=False): You can pass contact information inline here just like you can for the `to`. """ - pdf: Required[Annotated[Union[str, Base64FileInput], PropertyInfo(format="base64")]] - """A 2 page PDF file. + pdf: Required[FileTypes] + """Represents a raw file upload. - The first page is the inside of the self-mailer and the second page is the - outside (where the address will be stamped on). + Sending the actual file requires a `multipart/form-data` request; in + `application/json` request bodies, supply a URL instead. """ size: Required[Literal["8.5x11_bifold", "8.5x11_trifold", "9.5x16_trifold"]] @@ -402,6 +408,8 @@ class SelfMailerCreateWithPdfFile(TypedDict, total=False): You can use this parameter to schedule orders for a future date. """ + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + SelfMailerCreateWithPdfFileFrom: TypeAlias = Union[ ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str diff --git a/src/postgrid/types/print_mail/self_mailer_create_response.py b/src/postgrid/types/print_mail/self_mailer_create_response.py new file mode 100644 index 0000000..3ec1df2 --- /dev/null +++ b/src/postgrid/types/print_mail/self_mailer_create_response.py @@ -0,0 +1,10 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Union +from typing_extensions import TypeAlias + +from .self_mailer import SelfMailer + +__all__ = ["SelfMailerCreateResponse"] + +SelfMailerCreateResponse: TypeAlias = Union[SelfMailer, SelfMailer] diff --git a/src/postgrid/types/print_mail/snap_pack_list_response.py b/src/postgrid/types/print_mail/snap_pack.py similarity index 98% rename from src/postgrid/types/print_mail/snap_pack_list_response.py rename to src/postgrid/types/print_mail/snap_pack.py index 80e17b6..4fc818a 100644 --- a/src/postgrid/types/print_mail/snap_pack_list_response.py +++ b/src/postgrid/types/print_mail/snap_pack.py @@ -10,7 +10,7 @@ from .contact import Contact from ..._models import BaseModel -__all__ = ["SnapPackListResponse", "Cancellation"] +__all__ = ["SnapPack", "Cancellation"] class Cancellation(BaseModel): @@ -29,7 +29,7 @@ class Cancellation(BaseModel): """An optional note provided by the user who cancelled the order.""" -class SnapPackListResponse(BaseModel): +class SnapPack(BaseModel): id: str """A unique ID prefixed with snap*pack*""" diff --git a/src/postgrid/types/print_mail/snap_pack_create_params.py b/src/postgrid/types/print_mail/snap_pack_create_params.py index 70fb869..70975b9 100644 --- a/src/postgrid/types/print_mail/snap_pack_create_params.py +++ b/src/postgrid/types/print_mail/snap_pack_create_params.py @@ -6,6 +6,7 @@ from datetime import datetime from typing_extensions import Literal, Required, Annotated, TypeAlias, TypedDict +from ..._types import FileTypes from ..._utils import PropertyInfo from .contact_create_with_first_name_param import ContactCreateWithFirstNameParam from .contact_create_with_company_name_param import ContactCreateWithCompanyNameParam @@ -115,6 +116,8 @@ class SnapPackCreateWithHTML(TypedDict, total=False): You can use this parameter to schedule orders for a future date. """ + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + SnapPackCreateWithHTMLFrom: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] @@ -212,6 +215,8 @@ class SnapPackCreateWithTemplate(TypedDict, total=False): You can use this parameter to schedule orders for a future date. """ + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + SnapPackCreateWithTemplateFrom: TypeAlias = Union[ ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str @@ -228,7 +233,7 @@ class SnapPackCreateWithPdf(TypedDict, total=False): contact. """ - pdf: Required[str] + pdf: Required[Union[str, FileTypes]] """ A URL or a multipart-uploaded two-page PDF (first page is the outside, second page is the inside) that matches the selected snap pack size. @@ -305,6 +310,8 @@ class SnapPackCreateWithPdf(TypedDict, total=False): You can use this parameter to schedule orders for a future date. """ + idempotency_key: Annotated[str, PropertyInfo(alias="idempotency-key")] + SnapPackCreateWithPdfFrom: TypeAlias = Union[ContactCreateWithFirstNameParam, ContactCreateWithCompanyNameParam, str] diff --git a/src/postgrid/types/print_mail/snap_pack_create_response.py b/src/postgrid/types/print_mail/snap_pack_create_response.py index 801446c..1771d9a 100644 --- a/src/postgrid/types/print_mail/snap_pack_create_response.py +++ b/src/postgrid/types/print_mail/snap_pack_create_response.py @@ -1,196 +1,10 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import builtins -from typing import Dict, Optional -from datetime import datetime -from typing_extensions import Literal +from typing import Union +from typing_extensions import TypeAlias -from pydantic import Field as FieldInfo +from .snap_pack import SnapPack -from .contact import Contact -from ..._models import BaseModel +__all__ = ["SnapPackCreateResponse"] -__all__ = ["SnapPackCreateResponse", "Cancellation"] - - -class Cancellation(BaseModel): - """The cancellation details of this order. - - Populated if the order has been cancelled. - """ - - reason: Literal["user_initiated", "invalid_content", "invalid_order_mailing_class"] - """The reason for the cancellation.""" - - cancelled_by_user: Optional[str] = FieldInfo(alias="cancelledByUser", default=None) - """The user ID who cancelled the order.""" - - note: Optional[str] = None - """An optional note provided by the user who cancelled the order.""" - - -class SnapPackCreateResponse(BaseModel): - id: str - """A unique ID prefixed with snap*pack*""" - - created_at: datetime = FieldInfo(alias="createdAt") - """The UTC time at which this resource was created.""" - - from_: Contact = FieldInfo(alias="from") - """The contact information of the sender.""" - - live: bool - """`true` if this is a live mode resource else `false`.""" - - mailing_class: Literal[ - "first_class", - "standard_class", - "express", - "certified", - "certified_return_receipt", - "registered", - "usps_first_class", - "usps_standard_class", - "usps_eddm", - "usps_express_2_day", - "usps_express_3_day", - "usps_first_class_certified", - "usps_first_class_certified_return_receipt", - "usps_first_class_registered", - "usps_express_3_day_signature_confirmation", - "usps_express_3_day_certified", - "usps_express_3_day_certified_return_receipt", - "ca_post_lettermail", - "ca_post_personalized", - "ca_post_neighbourhood_mail", - "ups_express_overnight", - "ups_express_2_day", - "ups_express_3_day", - "royal_mail_first_class", - "royal_mail_second_class", - "au_post_second_class", - ] = FieldInfo(alias="mailingClass") - """The mailing class of this order. - - This determines the speed and cost of delivery. See `OrderMailingClass` for more - details. - """ - - object: Literal["snap_pack"] - """Always `snap_pack`.""" - - send_date: datetime = FieldInfo(alias="sendDate") - """This order will transition from `ready` to `printing` on the day after this - date. - - For example, if this is a date on Tuesday, the order will transition to - `printing` on Wednesday at midnight eastern time. - """ - - size: Literal["8.5x11_bifold_v"] - """Enum representing the supported snap pack sizes.""" - - status: Literal["ready", "printing", "processed_for_delivery", "completed", "cancelled"] - """See `OrderStatus` for more details on the status of this order.""" - - to: Contact - """The recipient of this order. - - This will be provided even if you delete the underlying contact. - """ - - updated_at: datetime = FieldInfo(alias="updatedAt") - """The UTC time at which this resource was last updated.""" - - cancellation: Optional[Cancellation] = None - """The cancellation details of this order. - - Populated if the order has been cancelled. - """ - - description: Optional[str] = None - """An optional string describing this resource. - - Will be visible in the API and the dashboard. - """ - - imb_date: Optional[datetime] = FieldInfo(alias="imbDate", default=None) - """The last date that the IMB status was updated. - - See `imbStatus` for more details. - """ - - imb_status: Optional[Literal["entered_mail_stream", "out_for_delivery", "returned_to_sender"]] = FieldInfo( - alias="imbStatus", default=None - ) - """The Intelligent Mail Barcode (IMB) status of this order. - - Only populated for US-printed and US-destined orders. This is the most detailed - way to track non-express/certified orders. - """ - - imb_zip_code: Optional[str] = FieldInfo(alias="imbZIPCode", default=None) - """ - The most recent ZIP code of the USPS facility that the order has been processed - through. Only populated when an `imbStatus` is present. - """ - - inside_html: Optional[str] = FieldInfo(alias="insideHTML", default=None) - """ - The HTML content for the inside of the snap pack, when provided instead of a - template or PDF. - """ - - inside_template: Optional[str] = FieldInfo(alias="insideTemplate", default=None) - """ - The template ID for the inside of the snap pack, when provided instead of HTML - or PDF. - """ - - merge_variables: Optional[Dict[str, builtins.object]] = FieldInfo(alias="mergeVariables", default=None) - """ - These will be merged with the variables in the template or HTML you create this - order with. The keys in this object should match the variable names in the - template _exactly_ as they are case-sensitive. Note that these _do not_ apply to - PDFs uploaded with the order. - """ - - metadata: Optional[Dict[str, builtins.object]] = None - """See the section on Metadata.""" - - outside_html: Optional[str] = FieldInfo(alias="outsideHTML", default=None) - """ - The HTML content for the outside of the snap pack, when provided instead of a - template or PDF. - """ - - outside_template: Optional[str] = FieldInfo(alias="outsideTemplate", default=None) - """ - The template ID for the outside of the snap pack, when provided instead of HTML - or PDF. - """ - - tracking_number: Optional[str] = FieldInfo(alias="trackingNumber", default=None) - """The tracking number of this order. - - Populated after an express/certified order has been processed for delivery. - """ - - uploaded_pdf: Optional[str] = FieldInfo(alias="uploadedPDF", default=None) - """ - A signed URL to the uploaded PDF provided at creation time, if a PDF was - supplied. - """ - - url: Optional[str] = None - """PostGrid renders a PDF preview for all orders. - - This should be inspected to ensure that the order is correct before it is sent - out because it shows what will be printed and mailed to the recipient. Once the - PDF preview is generated, this field will be returned by all `GET` endpoints - which produce this order. - - This URL is a signed link to the PDF preview. It will expire after a short - period of time. If you need to access this URL after it has expired, you can - regenerate it by calling the `GET` endpoint again. - """ +SnapPackCreateResponse: TypeAlias = Union[SnapPack, SnapPack] diff --git a/src/postgrid/types/print_mail/snap_pack_delete_response.py b/src/postgrid/types/print_mail/snap_pack_delete_response.py deleted file mode 100644 index 87b05fd..0000000 --- a/src/postgrid/types/print_mail/snap_pack_delete_response.py +++ /dev/null @@ -1,196 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import builtins -from typing import Dict, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .contact import Contact -from ..._models import BaseModel - -__all__ = ["SnapPackDeleteResponse", "Cancellation"] - - -class Cancellation(BaseModel): - """The cancellation details of this order. - - Populated if the order has been cancelled. - """ - - reason: Literal["user_initiated", "invalid_content", "invalid_order_mailing_class"] - """The reason for the cancellation.""" - - cancelled_by_user: Optional[str] = FieldInfo(alias="cancelledByUser", default=None) - """The user ID who cancelled the order.""" - - note: Optional[str] = None - """An optional note provided by the user who cancelled the order.""" - - -class SnapPackDeleteResponse(BaseModel): - id: str - """A unique ID prefixed with snap*pack*""" - - created_at: datetime = FieldInfo(alias="createdAt") - """The UTC time at which this resource was created.""" - - from_: Contact = FieldInfo(alias="from") - """The contact information of the sender.""" - - live: bool - """`true` if this is a live mode resource else `false`.""" - - mailing_class: Literal[ - "first_class", - "standard_class", - "express", - "certified", - "certified_return_receipt", - "registered", - "usps_first_class", - "usps_standard_class", - "usps_eddm", - "usps_express_2_day", - "usps_express_3_day", - "usps_first_class_certified", - "usps_first_class_certified_return_receipt", - "usps_first_class_registered", - "usps_express_3_day_signature_confirmation", - "usps_express_3_day_certified", - "usps_express_3_day_certified_return_receipt", - "ca_post_lettermail", - "ca_post_personalized", - "ca_post_neighbourhood_mail", - "ups_express_overnight", - "ups_express_2_day", - "ups_express_3_day", - "royal_mail_first_class", - "royal_mail_second_class", - "au_post_second_class", - ] = FieldInfo(alias="mailingClass") - """The mailing class of this order. - - This determines the speed and cost of delivery. See `OrderMailingClass` for more - details. - """ - - object: Literal["snap_pack"] - """Always `snap_pack`.""" - - send_date: datetime = FieldInfo(alias="sendDate") - """This order will transition from `ready` to `printing` on the day after this - date. - - For example, if this is a date on Tuesday, the order will transition to - `printing` on Wednesday at midnight eastern time. - """ - - size: Literal["8.5x11_bifold_v"] - """Enum representing the supported snap pack sizes.""" - - status: Literal["ready", "printing", "processed_for_delivery", "completed", "cancelled"] - """See `OrderStatus` for more details on the status of this order.""" - - to: Contact - """The recipient of this order. - - This will be provided even if you delete the underlying contact. - """ - - updated_at: datetime = FieldInfo(alias="updatedAt") - """The UTC time at which this resource was last updated.""" - - cancellation: Optional[Cancellation] = None - """The cancellation details of this order. - - Populated if the order has been cancelled. - """ - - description: Optional[str] = None - """An optional string describing this resource. - - Will be visible in the API and the dashboard. - """ - - imb_date: Optional[datetime] = FieldInfo(alias="imbDate", default=None) - """The last date that the IMB status was updated. - - See `imbStatus` for more details. - """ - - imb_status: Optional[Literal["entered_mail_stream", "out_for_delivery", "returned_to_sender"]] = FieldInfo( - alias="imbStatus", default=None - ) - """The Intelligent Mail Barcode (IMB) status of this order. - - Only populated for US-printed and US-destined orders. This is the most detailed - way to track non-express/certified orders. - """ - - imb_zip_code: Optional[str] = FieldInfo(alias="imbZIPCode", default=None) - """ - The most recent ZIP code of the USPS facility that the order has been processed - through. Only populated when an `imbStatus` is present. - """ - - inside_html: Optional[str] = FieldInfo(alias="insideHTML", default=None) - """ - The HTML content for the inside of the snap pack, when provided instead of a - template or PDF. - """ - - inside_template: Optional[str] = FieldInfo(alias="insideTemplate", default=None) - """ - The template ID for the inside of the snap pack, when provided instead of HTML - or PDF. - """ - - merge_variables: Optional[Dict[str, builtins.object]] = FieldInfo(alias="mergeVariables", default=None) - """ - These will be merged with the variables in the template or HTML you create this - order with. The keys in this object should match the variable names in the - template _exactly_ as they are case-sensitive. Note that these _do not_ apply to - PDFs uploaded with the order. - """ - - metadata: Optional[Dict[str, builtins.object]] = None - """See the section on Metadata.""" - - outside_html: Optional[str] = FieldInfo(alias="outsideHTML", default=None) - """ - The HTML content for the outside of the snap pack, when provided instead of a - template or PDF. - """ - - outside_template: Optional[str] = FieldInfo(alias="outsideTemplate", default=None) - """ - The template ID for the outside of the snap pack, when provided instead of HTML - or PDF. - """ - - tracking_number: Optional[str] = FieldInfo(alias="trackingNumber", default=None) - """The tracking number of this order. - - Populated after an express/certified order has been processed for delivery. - """ - - uploaded_pdf: Optional[str] = FieldInfo(alias="uploadedPDF", default=None) - """ - A signed URL to the uploaded PDF provided at creation time, if a PDF was - supplied. - """ - - url: Optional[str] = None - """PostGrid renders a PDF preview for all orders. - - This should be inspected to ensure that the order is correct before it is sent - out because it shows what will be printed and mailed to the recipient. Once the - PDF preview is generated, this field will be returned by all `GET` endpoints - which produce this order. - - This URL is a signed link to the PDF preview. It will expire after a short - period of time. If you need to access this URL after it has expired, you can - regenerate it by calling the `GET` endpoint again. - """ diff --git a/src/postgrid/types/print_mail/snap_pack_progressions_response.py b/src/postgrid/types/print_mail/snap_pack_progressions_response.py deleted file mode 100644 index 10b5434..0000000 --- a/src/postgrid/types/print_mail/snap_pack_progressions_response.py +++ /dev/null @@ -1,196 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import builtins -from typing import Dict, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .contact import Contact -from ..._models import BaseModel - -__all__ = ["SnapPackProgressionsResponse", "Cancellation"] - - -class Cancellation(BaseModel): - """The cancellation details of this order. - - Populated if the order has been cancelled. - """ - - reason: Literal["user_initiated", "invalid_content", "invalid_order_mailing_class"] - """The reason for the cancellation.""" - - cancelled_by_user: Optional[str] = FieldInfo(alias="cancelledByUser", default=None) - """The user ID who cancelled the order.""" - - note: Optional[str] = None - """An optional note provided by the user who cancelled the order.""" - - -class SnapPackProgressionsResponse(BaseModel): - id: str - """A unique ID prefixed with snap*pack*""" - - created_at: datetime = FieldInfo(alias="createdAt") - """The UTC time at which this resource was created.""" - - from_: Contact = FieldInfo(alias="from") - """The contact information of the sender.""" - - live: bool - """`true` if this is a live mode resource else `false`.""" - - mailing_class: Literal[ - "first_class", - "standard_class", - "express", - "certified", - "certified_return_receipt", - "registered", - "usps_first_class", - "usps_standard_class", - "usps_eddm", - "usps_express_2_day", - "usps_express_3_day", - "usps_first_class_certified", - "usps_first_class_certified_return_receipt", - "usps_first_class_registered", - "usps_express_3_day_signature_confirmation", - "usps_express_3_day_certified", - "usps_express_3_day_certified_return_receipt", - "ca_post_lettermail", - "ca_post_personalized", - "ca_post_neighbourhood_mail", - "ups_express_overnight", - "ups_express_2_day", - "ups_express_3_day", - "royal_mail_first_class", - "royal_mail_second_class", - "au_post_second_class", - ] = FieldInfo(alias="mailingClass") - """The mailing class of this order. - - This determines the speed and cost of delivery. See `OrderMailingClass` for more - details. - """ - - object: Literal["snap_pack"] - """Always `snap_pack`.""" - - send_date: datetime = FieldInfo(alias="sendDate") - """This order will transition from `ready` to `printing` on the day after this - date. - - For example, if this is a date on Tuesday, the order will transition to - `printing` on Wednesday at midnight eastern time. - """ - - size: Literal["8.5x11_bifold_v"] - """Enum representing the supported snap pack sizes.""" - - status: Literal["ready", "printing", "processed_for_delivery", "completed", "cancelled"] - """See `OrderStatus` for more details on the status of this order.""" - - to: Contact - """The recipient of this order. - - This will be provided even if you delete the underlying contact. - """ - - updated_at: datetime = FieldInfo(alias="updatedAt") - """The UTC time at which this resource was last updated.""" - - cancellation: Optional[Cancellation] = None - """The cancellation details of this order. - - Populated if the order has been cancelled. - """ - - description: Optional[str] = None - """An optional string describing this resource. - - Will be visible in the API and the dashboard. - """ - - imb_date: Optional[datetime] = FieldInfo(alias="imbDate", default=None) - """The last date that the IMB status was updated. - - See `imbStatus` for more details. - """ - - imb_status: Optional[Literal["entered_mail_stream", "out_for_delivery", "returned_to_sender"]] = FieldInfo( - alias="imbStatus", default=None - ) - """The Intelligent Mail Barcode (IMB) status of this order. - - Only populated for US-printed and US-destined orders. This is the most detailed - way to track non-express/certified orders. - """ - - imb_zip_code: Optional[str] = FieldInfo(alias="imbZIPCode", default=None) - """ - The most recent ZIP code of the USPS facility that the order has been processed - through. Only populated when an `imbStatus` is present. - """ - - inside_html: Optional[str] = FieldInfo(alias="insideHTML", default=None) - """ - The HTML content for the inside of the snap pack, when provided instead of a - template or PDF. - """ - - inside_template: Optional[str] = FieldInfo(alias="insideTemplate", default=None) - """ - The template ID for the inside of the snap pack, when provided instead of HTML - or PDF. - """ - - merge_variables: Optional[Dict[str, builtins.object]] = FieldInfo(alias="mergeVariables", default=None) - """ - These will be merged with the variables in the template or HTML you create this - order with. The keys in this object should match the variable names in the - template _exactly_ as they are case-sensitive. Note that these _do not_ apply to - PDFs uploaded with the order. - """ - - metadata: Optional[Dict[str, builtins.object]] = None - """See the section on Metadata.""" - - outside_html: Optional[str] = FieldInfo(alias="outsideHTML", default=None) - """ - The HTML content for the outside of the snap pack, when provided instead of a - template or PDF. - """ - - outside_template: Optional[str] = FieldInfo(alias="outsideTemplate", default=None) - """ - The template ID for the outside of the snap pack, when provided instead of HTML - or PDF. - """ - - tracking_number: Optional[str] = FieldInfo(alias="trackingNumber", default=None) - """The tracking number of this order. - - Populated after an express/certified order has been processed for delivery. - """ - - uploaded_pdf: Optional[str] = FieldInfo(alias="uploadedPDF", default=None) - """ - A signed URL to the uploaded PDF provided at creation time, if a PDF was - supplied. - """ - - url: Optional[str] = None - """PostGrid renders a PDF preview for all orders. - - This should be inspected to ensure that the order is correct before it is sent - out because it shows what will be printed and mailed to the recipient. Once the - PDF preview is generated, this field will be returned by all `GET` endpoints - which produce this order. - - This URL is a signed link to the PDF preview. It will expire after a short - period of time. If you need to access this URL after it has expired, you can - regenerate it by calling the `GET` endpoint again. - """ diff --git a/src/postgrid/types/print_mail/snap_pack_retrieve_response.py b/src/postgrid/types/print_mail/snap_pack_retrieve_response.py deleted file mode 100644 index 49dd283..0000000 --- a/src/postgrid/types/print_mail/snap_pack_retrieve_response.py +++ /dev/null @@ -1,196 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import builtins -from typing import Dict, Optional -from datetime import datetime -from typing_extensions import Literal - -from pydantic import Field as FieldInfo - -from .contact import Contact -from ..._models import BaseModel - -__all__ = ["SnapPackRetrieveResponse", "Cancellation"] - - -class Cancellation(BaseModel): - """The cancellation details of this order. - - Populated if the order has been cancelled. - """ - - reason: Literal["user_initiated", "invalid_content", "invalid_order_mailing_class"] - """The reason for the cancellation.""" - - cancelled_by_user: Optional[str] = FieldInfo(alias="cancelledByUser", default=None) - """The user ID who cancelled the order.""" - - note: Optional[str] = None - """An optional note provided by the user who cancelled the order.""" - - -class SnapPackRetrieveResponse(BaseModel): - id: str - """A unique ID prefixed with snap*pack*""" - - created_at: datetime = FieldInfo(alias="createdAt") - """The UTC time at which this resource was created.""" - - from_: Contact = FieldInfo(alias="from") - """The contact information of the sender.""" - - live: bool - """`true` if this is a live mode resource else `false`.""" - - mailing_class: Literal[ - "first_class", - "standard_class", - "express", - "certified", - "certified_return_receipt", - "registered", - "usps_first_class", - "usps_standard_class", - "usps_eddm", - "usps_express_2_day", - "usps_express_3_day", - "usps_first_class_certified", - "usps_first_class_certified_return_receipt", - "usps_first_class_registered", - "usps_express_3_day_signature_confirmation", - "usps_express_3_day_certified", - "usps_express_3_day_certified_return_receipt", - "ca_post_lettermail", - "ca_post_personalized", - "ca_post_neighbourhood_mail", - "ups_express_overnight", - "ups_express_2_day", - "ups_express_3_day", - "royal_mail_first_class", - "royal_mail_second_class", - "au_post_second_class", - ] = FieldInfo(alias="mailingClass") - """The mailing class of this order. - - This determines the speed and cost of delivery. See `OrderMailingClass` for more - details. - """ - - object: Literal["snap_pack"] - """Always `snap_pack`.""" - - send_date: datetime = FieldInfo(alias="sendDate") - """This order will transition from `ready` to `printing` on the day after this - date. - - For example, if this is a date on Tuesday, the order will transition to - `printing` on Wednesday at midnight eastern time. - """ - - size: Literal["8.5x11_bifold_v"] - """Enum representing the supported snap pack sizes.""" - - status: Literal["ready", "printing", "processed_for_delivery", "completed", "cancelled"] - """See `OrderStatus` for more details on the status of this order.""" - - to: Contact - """The recipient of this order. - - This will be provided even if you delete the underlying contact. - """ - - updated_at: datetime = FieldInfo(alias="updatedAt") - """The UTC time at which this resource was last updated.""" - - cancellation: Optional[Cancellation] = None - """The cancellation details of this order. - - Populated if the order has been cancelled. - """ - - description: Optional[str] = None - """An optional string describing this resource. - - Will be visible in the API and the dashboard. - """ - - imb_date: Optional[datetime] = FieldInfo(alias="imbDate", default=None) - """The last date that the IMB status was updated. - - See `imbStatus` for more details. - """ - - imb_status: Optional[Literal["entered_mail_stream", "out_for_delivery", "returned_to_sender"]] = FieldInfo( - alias="imbStatus", default=None - ) - """The Intelligent Mail Barcode (IMB) status of this order. - - Only populated for US-printed and US-destined orders. This is the most detailed - way to track non-express/certified orders. - """ - - imb_zip_code: Optional[str] = FieldInfo(alias="imbZIPCode", default=None) - """ - The most recent ZIP code of the USPS facility that the order has been processed - through. Only populated when an `imbStatus` is present. - """ - - inside_html: Optional[str] = FieldInfo(alias="insideHTML", default=None) - """ - The HTML content for the inside of the snap pack, when provided instead of a - template or PDF. - """ - - inside_template: Optional[str] = FieldInfo(alias="insideTemplate", default=None) - """ - The template ID for the inside of the snap pack, when provided instead of HTML - or PDF. - """ - - merge_variables: Optional[Dict[str, builtins.object]] = FieldInfo(alias="mergeVariables", default=None) - """ - These will be merged with the variables in the template or HTML you create this - order with. The keys in this object should match the variable names in the - template _exactly_ as they are case-sensitive. Note that these _do not_ apply to - PDFs uploaded with the order. - """ - - metadata: Optional[Dict[str, builtins.object]] = None - """See the section on Metadata.""" - - outside_html: Optional[str] = FieldInfo(alias="outsideHTML", default=None) - """ - The HTML content for the outside of the snap pack, when provided instead of a - template or PDF. - """ - - outside_template: Optional[str] = FieldInfo(alias="outsideTemplate", default=None) - """ - The template ID for the outside of the snap pack, when provided instead of HTML - or PDF. - """ - - tracking_number: Optional[str] = FieldInfo(alias="trackingNumber", default=None) - """The tracking number of this order. - - Populated after an express/certified order has been processed for delivery. - """ - - uploaded_pdf: Optional[str] = FieldInfo(alias="uploadedPDF", default=None) - """ - A signed URL to the uploaded PDF provided at creation time, if a PDF was - supplied. - """ - - url: Optional[str] = None - """PostGrid renders a PDF preview for all orders. - - This should be inspected to ensure that the order is correct before it is sent - out because it shows what will be printed and mailed to the recipient. Once the - PDF preview is generated, this field will be returned by all `GET` endpoints - which produce this order. - - This URL is a signed link to the PDF preview. It will expire after a short - period of time. If you need to access this URL after it has expired, you can - regenerate it by calling the `GET` endpoint again. - """ diff --git a/tests/api_resources/print_mail/test_campaigns.py b/tests/api_resources/print_mail/test_campaigns.py index 0b7db6e..31f5464 100644 --- a/tests/api_resources/print_mail/test_campaigns.py +++ b/tests/api_resources/print_mail/test_campaigns.py @@ -40,7 +40,7 @@ def test_method_create_with_all_params(self, client: PostGrid) -> None: "currency_code": "CAD", "description": "description", "envelope": "envelope", - "letter_pdf": "U3RhaW5sZXNzIHJvY2tz", + "letter_pdf": "https://example.com", "letter_settings": {"color": True}, "letter_template": "letterTemplate", "logo": "https://example.com", @@ -198,7 +198,7 @@ def test_method_update_with_all_params(self, client: PostGrid) -> None: "currency_code": "CAD", "description": "description", "envelope": "envelope", - "letter_pdf": "U3RhaW5sZXNzIHJvY2tz", + "letter_pdf": "https://example.com", "letter_settings": {"color": True}, "letter_template": "letterTemplate", "logo": "https://example.com", @@ -458,7 +458,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncPostGrid) "currency_code": "CAD", "description": "description", "envelope": "envelope", - "letter_pdf": "U3RhaW5sZXNzIHJvY2tz", + "letter_pdf": "https://example.com", "letter_settings": {"color": True}, "letter_template": "letterTemplate", "logo": "https://example.com", @@ -616,7 +616,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncPostGrid) "currency_code": "CAD", "description": "description", "envelope": "envelope", - "letter_pdf": "U3RhaW5sZXNzIHJvY2tz", + "letter_pdf": "https://example.com", "letter_settings": {"color": True}, "letter_template": "letterTemplate", "logo": "https://example.com", diff --git a/tests/api_resources/print_mail/test_cheques.py b/tests/api_resources/print_mail/test_cheques.py index dd9f113..7d4ed28 100644 --- a/tests/api_resources/print_mail/test_cheques.py +++ b/tests/api_resources/print_mail/test_cheques.py @@ -49,7 +49,7 @@ def test_method_create_with_all_params(self, client: PostGrid) -> None: }, envelope="standard", letter_html="letterHTML", - letter_pdf="U3RhaW5sZXNzIHJvY2tz", + letter_pdf="https://example.com", letter_settings={"placement": "before_cheque"}, letter_template="letterTemplate", logo="https://example.com", @@ -81,6 +81,7 @@ def test_method_create_with_all_params(self, client: PostGrid) -> None: return_envelope="returnEnvelope", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), size="us_letter", + idempotency_key="idempotency-key", ) assert_matches_type(Cheque, cheque, path=["response"]) @@ -443,7 +444,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncPostGrid) }, envelope="standard", letter_html="letterHTML", - letter_pdf="U3RhaW5sZXNzIHJvY2tz", + letter_pdf="https://example.com", letter_settings={"placement": "before_cheque"}, letter_template="letterTemplate", logo="https://example.com", @@ -475,6 +476,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncPostGrid) return_envelope="returnEnvelope", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), size="us_letter", + idempotency_key="idempotency-key", ) assert_matches_type(Cheque, cheque, path=["response"]) diff --git a/tests/api_resources/print_mail/test_letters.py b/tests/api_resources/print_mail/test_letters.py index cdbb8b5..7592e9f 100644 --- a/tests/api_resources/print_mail/test_letters.py +++ b/tests/api_resources/print_mail/test_letters.py @@ -13,6 +13,7 @@ from postgrid.pagination import SyncSkipLimit, AsyncSkipLimit from postgrid.types.print_mail import ( Letter, + LetterCreateResponse, LetterRetrieveURLResponse, ) @@ -38,7 +39,7 @@ def test_method_create_overload_1(self, client: PostGrid) -> None: "first_name": "firstName", }, ) - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -115,8 +116,9 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non return_envelope="returnEnvelope", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), size="us_letter", + idempotency_key="idempotency-key", ) - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -138,7 +140,7 @@ def test_raw_response_create_overload_1(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" letter = response.parse() - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -160,7 +162,7 @@ def test_streaming_response_create_overload_1(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" letter = response.parse() - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) assert cast(Any, response.is_closed) is True @@ -180,7 +182,7 @@ def test_method_create_overload_2(self, client: PostGrid) -> None: "first_name": "firstName", }, ) - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -257,8 +259,9 @@ def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> Non return_envelope="returnEnvelope", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), size="us_letter", + idempotency_key="idempotency-key", ) - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -280,7 +283,7 @@ def test_raw_response_create_overload_2(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" letter = response.parse() - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -302,7 +305,7 @@ def test_streaming_response_create_overload_2(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" letter = response.parse() - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) assert cast(Any, response.is_closed) is True @@ -322,7 +325,7 @@ def test_method_create_overload_3(self, client: PostGrid) -> None: "first_name": "firstName", }, ) - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -399,8 +402,9 @@ def test_method_create_with_all_params_overload_3(self, client: PostGrid) -> Non return_envelope="returnEnvelope", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), size="us_letter", + idempotency_key="idempotency-key", ) - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -422,7 +426,7 @@ def test_raw_response_create_overload_3(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" letter = response.parse() - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -444,7 +448,7 @@ def test_streaming_response_create_overload_3(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" letter = response.parse() - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) assert cast(Any, response.is_closed) is True @@ -722,7 +726,7 @@ async def test_method_create_overload_1(self, async_client: AsyncPostGrid) -> No "first_name": "firstName", }, ) - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -799,8 +803,9 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn return_envelope="returnEnvelope", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), size="us_letter", + idempotency_key="idempotency-key", ) - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -822,7 +827,7 @@ async def test_raw_response_create_overload_1(self, async_client: AsyncPostGrid) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" letter = await response.parse() - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -844,7 +849,7 @@ async def test_streaming_response_create_overload_1(self, async_client: AsyncPos assert response.http_request.headers.get("X-Stainless-Lang") == "python" letter = await response.parse() - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) assert cast(Any, response.is_closed) is True @@ -864,7 +869,7 @@ async def test_method_create_overload_2(self, async_client: AsyncPostGrid) -> No "first_name": "firstName", }, ) - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -941,8 +946,9 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn return_envelope="returnEnvelope", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), size="us_letter", + idempotency_key="idempotency-key", ) - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -964,7 +970,7 @@ async def test_raw_response_create_overload_2(self, async_client: AsyncPostGrid) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" letter = await response.parse() - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -986,7 +992,7 @@ async def test_streaming_response_create_overload_2(self, async_client: AsyncPos assert response.http_request.headers.get("X-Stainless-Lang") == "python" letter = await response.parse() - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) assert cast(Any, response.is_closed) is True @@ -1006,7 +1012,7 @@ async def test_method_create_overload_3(self, async_client: AsyncPostGrid) -> No "first_name": "firstName", }, ) - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1083,8 +1089,9 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn return_envelope="returnEnvelope", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), size="us_letter", + idempotency_key="idempotency-key", ) - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1106,7 +1113,7 @@ async def test_raw_response_create_overload_3(self, async_client: AsyncPostGrid) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" letter = await response.parse() - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1128,7 +1135,7 @@ async def test_streaming_response_create_overload_3(self, async_client: AsyncPos assert response.http_request.headers.get("X-Stainless-Lang") == "python" letter = await response.parse() - assert_matches_type(Letter, letter, path=["response"]) + assert_matches_type(LetterCreateResponse, letter, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/print_mail/test_postcards.py b/tests/api_resources/print_mail/test_postcards.py index 8f2fb46..c661d0c 100644 --- a/tests/api_resources/print_mail/test_postcards.py +++ b/tests/api_resources/print_mail/test_postcards.py @@ -13,6 +13,7 @@ from postgrid.pagination import SyncSkipLimit, AsyncSkipLimit from postgrid.types.print_mail import ( Postcard, + PostcardCreateResponse, PostcardRetrieveURLResponse, ) @@ -35,7 +36,7 @@ def test_method_create_overload_1(self, client: PostGrid) -> None: "first_name": "firstName", }, ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -88,8 +89,9 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non metadata={"foo": "bar"}, paper="standard", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -108,7 +110,7 @@ def test_raw_response_create_overload_1(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -127,7 +129,7 @@ def test_streaming_response_create_overload_1(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) assert cast(Any, response.is_closed) is True @@ -144,7 +146,7 @@ def test_method_create_overload_2(self, client: PostGrid) -> None: "first_name": "firstName", }, ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -197,8 +199,9 @@ def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> Non metadata={"foo": "bar"}, paper="standard", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -217,7 +220,7 @@ def test_raw_response_create_overload_2(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -236,7 +239,7 @@ def test_streaming_response_create_overload_2(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) assert cast(Any, response.is_closed) is True @@ -252,7 +255,7 @@ def test_method_create_overload_3(self, client: PostGrid) -> None: "first_name": "firstName", }, ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -304,8 +307,9 @@ def test_method_create_with_all_params_overload_3(self, client: PostGrid) -> Non metadata={"foo": "bar"}, paper="standard", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -323,7 +327,7 @@ def test_raw_response_create_overload_3(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -341,7 +345,7 @@ def test_streaming_response_create_overload_3(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) assert cast(Any, response.is_closed) is True @@ -349,7 +353,7 @@ def test_streaming_response_create_overload_3(self, client: PostGrid) -> None: @parametrize def test_method_create_overload_4(self, client: PostGrid) -> None: postcard = client.print_mail.postcards.create( - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="6x4", to={ "address_line1": "addressLine1", @@ -357,13 +361,13 @@ def test_method_create_overload_4(self, client: PostGrid) -> None: "first_name": "firstName", }, ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_method_create_with_all_params_overload_4(self, client: PostGrid) -> None: postcard = client.print_mail.postcards.create( - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="6x4", to={ "address_line1": "addressLine1", @@ -409,14 +413,15 @@ def test_method_create_with_all_params_overload_4(self, client: PostGrid) -> Non metadata={"foo": "bar"}, paper="standard", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_raw_response_create_overload_4(self, client: PostGrid) -> None: response = client.print_mail.postcards.with_raw_response.create( - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="6x4", to={ "address_line1": "addressLine1", @@ -428,13 +433,13 @@ def test_raw_response_create_overload_4(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize def test_streaming_response_create_overload_4(self, client: PostGrid) -> None: with client.print_mail.postcards.with_streaming_response.create( - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="6x4", to={ "address_line1": "addressLine1", @@ -446,7 +451,7 @@ def test_streaming_response_create_overload_4(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) assert cast(Any, response.is_closed) is True @@ -721,7 +726,7 @@ async def test_method_create_overload_1(self, async_client: AsyncPostGrid) -> No "first_name": "firstName", }, ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -774,8 +779,9 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn metadata={"foo": "bar"}, paper="standard", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -794,7 +800,7 @@ async def test_raw_response_create_overload_1(self, async_client: AsyncPostGrid) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = await response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -813,7 +819,7 @@ async def test_streaming_response_create_overload_1(self, async_client: AsyncPos assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = await response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) assert cast(Any, response.is_closed) is True @@ -830,7 +836,7 @@ async def test_method_create_overload_2(self, async_client: AsyncPostGrid) -> No "first_name": "firstName", }, ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -883,8 +889,9 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn metadata={"foo": "bar"}, paper="standard", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -903,7 +910,7 @@ async def test_raw_response_create_overload_2(self, async_client: AsyncPostGrid) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = await response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -922,7 +929,7 @@ async def test_streaming_response_create_overload_2(self, async_client: AsyncPos assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = await response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) assert cast(Any, response.is_closed) is True @@ -938,7 +945,7 @@ async def test_method_create_overload_3(self, async_client: AsyncPostGrid) -> No "first_name": "firstName", }, ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -990,8 +997,9 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn metadata={"foo": "bar"}, paper="standard", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1009,7 +1017,7 @@ async def test_raw_response_create_overload_3(self, async_client: AsyncPostGrid) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = await response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1027,7 +1035,7 @@ async def test_streaming_response_create_overload_3(self, async_client: AsyncPos assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = await response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) assert cast(Any, response.is_closed) is True @@ -1035,7 +1043,7 @@ async def test_streaming_response_create_overload_3(self, async_client: AsyncPos @parametrize async def test_method_create_overload_4(self, async_client: AsyncPostGrid) -> None: postcard = await async_client.print_mail.postcards.create( - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="6x4", to={ "address_line1": "addressLine1", @@ -1043,13 +1051,13 @@ async def test_method_create_overload_4(self, async_client: AsyncPostGrid) -> No "first_name": "firstName", }, ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_method_create_with_all_params_overload_4(self, async_client: AsyncPostGrid) -> None: postcard = await async_client.print_mail.postcards.create( - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="6x4", to={ "address_line1": "addressLine1", @@ -1095,14 +1103,15 @@ async def test_method_create_with_all_params_overload_4(self, async_client: Asyn metadata={"foo": "bar"}, paper="standard", send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_raw_response_create_overload_4(self, async_client: AsyncPostGrid) -> None: response = await async_client.print_mail.postcards.with_raw_response.create( - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="6x4", to={ "address_line1": "addressLine1", @@ -1114,13 +1123,13 @@ async def test_raw_response_create_overload_4(self, async_client: AsyncPostGrid) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = await response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize async def test_streaming_response_create_overload_4(self, async_client: AsyncPostGrid) -> None: async with async_client.print_mail.postcards.with_streaming_response.create( - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="6x4", to={ "address_line1": "addressLine1", @@ -1132,7 +1141,7 @@ async def test_streaming_response_create_overload_4(self, async_client: AsyncPos assert response.http_request.headers.get("X-Stainless-Lang") == "python" postcard = await response.parse() - assert_matches_type(Postcard, postcard, path=["response"]) + assert_matches_type(PostcardCreateResponse, postcard, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/print_mail/test_self_mailers.py b/tests/api_resources/print_mail/test_self_mailers.py index 9b9336d..8463a51 100644 --- a/tests/api_resources/print_mail/test_self_mailers.py +++ b/tests/api_resources/print_mail/test_self_mailers.py @@ -13,6 +13,7 @@ from postgrid.pagination import SyncSkipLimit, AsyncSkipLimit from postgrid.types.print_mail import ( SelfMailer, + SelfMailerCreateResponse, SelfMailerRetrieveURLResponse, ) @@ -40,7 +41,7 @@ def test_method_create_overload_1(self, client: PostGrid) -> None: "first_name": "firstName", }, ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -92,8 +93,9 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -117,7 +119,7 @@ def test_raw_response_create_overload_1(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -141,7 +143,7 @@ def test_streaming_response_create_overload_1(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) assert cast(Any, response.is_closed) is True @@ -163,7 +165,7 @@ def test_method_create_overload_2(self, client: PostGrid) -> None: "first_name": "firstName", }, ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -215,8 +217,9 @@ def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> Non merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -240,7 +243,7 @@ def test_raw_response_create_overload_2(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -264,7 +267,7 @@ def test_streaming_response_create_overload_2(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) assert cast(Any, response.is_closed) is True @@ -285,7 +288,7 @@ def test_method_create_overload_3(self, client: PostGrid) -> None: "first_name": "firstName", }, ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -336,8 +339,9 @@ def test_method_create_with_all_params_overload_3(self, client: PostGrid) -> Non merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -360,7 +364,7 @@ def test_raw_response_create_overload_3(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -383,7 +387,7 @@ def test_streaming_response_create_overload_3(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) assert cast(Any, response.is_closed) is True @@ -396,7 +400,7 @@ def test_method_create_overload_4(self, client: PostGrid) -> None: "country_code": "countryCode", "first_name": "firstName", }, - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="8.5x11_bifold", to={ "address_line1": "addressLine1", @@ -404,7 +408,7 @@ def test_method_create_overload_4(self, client: PostGrid) -> None: "first_name": "firstName", }, ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -429,7 +433,7 @@ def test_method_create_with_all_params_overload_4(self, client: PostGrid) -> Non "secret": True, "skip_verification": True, }, - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="8.5x11_bifold", to={ "address_line1": "addressLine1", @@ -455,8 +459,9 @@ def test_method_create_with_all_params_overload_4(self, client: PostGrid) -> Non merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -467,7 +472,7 @@ def test_raw_response_create_overload_4(self, client: PostGrid) -> None: "country_code": "countryCode", "first_name": "firstName", }, - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="8.5x11_bifold", to={ "address_line1": "addressLine1", @@ -479,7 +484,7 @@ def test_raw_response_create_overload_4(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -490,7 +495,7 @@ def test_streaming_response_create_overload_4(self, client: PostGrid) -> None: "country_code": "countryCode", "first_name": "firstName", }, - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="8.5x11_bifold", to={ "address_line1": "addressLine1", @@ -502,7 +507,7 @@ def test_streaming_response_create_overload_4(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) assert cast(Any, response.is_closed) is True @@ -736,7 +741,7 @@ async def test_method_create_overload_1(self, async_client: AsyncPostGrid) -> No "first_name": "firstName", }, ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -788,8 +793,9 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -813,7 +819,7 @@ async def test_raw_response_create_overload_1(self, async_client: AsyncPostGrid) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = await response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -837,7 +843,7 @@ async def test_streaming_response_create_overload_1(self, async_client: AsyncPos assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = await response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) assert cast(Any, response.is_closed) is True @@ -859,7 +865,7 @@ async def test_method_create_overload_2(self, async_client: AsyncPostGrid) -> No "first_name": "firstName", }, ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -911,8 +917,9 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -936,7 +943,7 @@ async def test_raw_response_create_overload_2(self, async_client: AsyncPostGrid) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = await response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -960,7 +967,7 @@ async def test_streaming_response_create_overload_2(self, async_client: AsyncPos assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = await response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) assert cast(Any, response.is_closed) is True @@ -981,7 +988,7 @@ async def test_method_create_overload_3(self, async_client: AsyncPostGrid) -> No "first_name": "firstName", }, ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1032,8 +1039,9 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1056,7 +1064,7 @@ async def test_raw_response_create_overload_3(self, async_client: AsyncPostGrid) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = await response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1079,7 +1087,7 @@ async def test_streaming_response_create_overload_3(self, async_client: AsyncPos assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = await response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) assert cast(Any, response.is_closed) is True @@ -1092,7 +1100,7 @@ async def test_method_create_overload_4(self, async_client: AsyncPostGrid) -> No "country_code": "countryCode", "first_name": "firstName", }, - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="8.5x11_bifold", to={ "address_line1": "addressLine1", @@ -1100,7 +1108,7 @@ async def test_method_create_overload_4(self, async_client: AsyncPostGrid) -> No "first_name": "firstName", }, ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1125,7 +1133,7 @@ async def test_method_create_with_all_params_overload_4(self, async_client: Asyn "secret": True, "skip_verification": True, }, - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="8.5x11_bifold", to={ "address_line1": "addressLine1", @@ -1151,8 +1159,9 @@ async def test_method_create_with_all_params_overload_4(self, async_client: Asyn merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1163,7 +1172,7 @@ async def test_raw_response_create_overload_4(self, async_client: AsyncPostGrid) "country_code": "countryCode", "first_name": "firstName", }, - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="8.5x11_bifold", to={ "address_line1": "addressLine1", @@ -1175,7 +1184,7 @@ async def test_raw_response_create_overload_4(self, async_client: AsyncPostGrid) assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = await response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1186,7 +1195,7 @@ async def test_streaming_response_create_overload_4(self, async_client: AsyncPos "country_code": "countryCode", "first_name": "firstName", }, - pdf="U3RhaW5sZXNzIHJvY2tz", + pdf=b"Example data", size="8.5x11_bifold", to={ "address_line1": "addressLine1", @@ -1198,7 +1207,7 @@ async def test_streaming_response_create_overload_4(self, async_client: AsyncPos assert response.http_request.headers.get("X-Stainless-Lang") == "python" self_mailer = await response.parse() - assert_matches_type(SelfMailer, self_mailer, path=["response"]) + assert_matches_type(SelfMailerCreateResponse, self_mailer, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/print_mail/test_snap_packs.py b/tests/api_resources/print_mail/test_snap_packs.py index 0b74ae2..e4dfdf0 100644 --- a/tests/api_resources/print_mail/test_snap_packs.py +++ b/tests/api_resources/print_mail/test_snap_packs.py @@ -12,11 +12,8 @@ from postgrid._utils import parse_datetime from postgrid.pagination import SyncSkipLimit, AsyncSkipLimit from postgrid.types.print_mail import ( - SnapPackListResponse, + SnapPack, SnapPackCreateResponse, - SnapPackDeleteResponse, - SnapPackRetrieveResponse, - SnapPackProgressionsResponse, SnapPackRetrieveCapabilitiesResponse, ) @@ -96,6 +93,7 @@ def test_method_create_with_all_params_overload_1(self, client: PostGrid) -> Non merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) assert_matches_type(SnapPackCreateResponse, snap_pack, path=["response"]) @@ -219,6 +217,7 @@ def test_method_create_with_all_params_overload_2(self, client: PostGrid) -> Non merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) assert_matches_type(SnapPackCreateResponse, snap_pack, path=["response"]) @@ -340,6 +339,7 @@ def test_method_create_with_all_params_overload_3(self, client: PostGrid) -> Non merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) assert_matches_type(SnapPackCreateResponse, snap_pack, path=["response"]) @@ -397,7 +397,7 @@ def test_method_retrieve(self, client: PostGrid) -> None: snap_pack = client.print_mail.snap_packs.retrieve( "id", ) - assert_matches_type(SnapPackRetrieveResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -409,7 +409,7 @@ def test_raw_response_retrieve(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = response.parse() - assert_matches_type(SnapPackRetrieveResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -421,7 +421,7 @@ def test_streaming_response_retrieve(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = response.parse() - assert_matches_type(SnapPackRetrieveResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) assert cast(Any, response.is_closed) is True @@ -437,7 +437,7 @@ def test_path_params_retrieve(self, client: PostGrid) -> None: @parametrize def test_method_list(self, client: PostGrid) -> None: snap_pack = client.print_mail.snap_packs.list() - assert_matches_type(SyncSkipLimit[SnapPackListResponse], snap_pack, path=["response"]) + assert_matches_type(SyncSkipLimit[SnapPack], snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -447,7 +447,7 @@ def test_method_list_with_all_params(self, client: PostGrid) -> None: search="search", skip=0, ) - assert_matches_type(SyncSkipLimit[SnapPackListResponse], snap_pack, path=["response"]) + assert_matches_type(SyncSkipLimit[SnapPack], snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -457,7 +457,7 @@ def test_raw_response_list(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = response.parse() - assert_matches_type(SyncSkipLimit[SnapPackListResponse], snap_pack, path=["response"]) + assert_matches_type(SyncSkipLimit[SnapPack], snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -467,7 +467,7 @@ def test_streaming_response_list(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = response.parse() - assert_matches_type(SyncSkipLimit[SnapPackListResponse], snap_pack, path=["response"]) + assert_matches_type(SyncSkipLimit[SnapPack], snap_pack, path=["response"]) assert cast(Any, response.is_closed) is True @@ -477,7 +477,7 @@ def test_method_delete(self, client: PostGrid) -> None: snap_pack = client.print_mail.snap_packs.delete( "id", ) - assert_matches_type(SnapPackDeleteResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -489,7 +489,7 @@ def test_raw_response_delete(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = response.parse() - assert_matches_type(SnapPackDeleteResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -501,7 +501,7 @@ def test_streaming_response_delete(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = response.parse() - assert_matches_type(SnapPackDeleteResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) assert cast(Any, response.is_closed) is True @@ -519,7 +519,7 @@ def test_method_progressions(self, client: PostGrid) -> None: snap_pack = client.print_mail.snap_packs.progressions( "id", ) - assert_matches_type(SnapPackProgressionsResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -531,7 +531,7 @@ def test_raw_response_progressions(self, client: PostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = response.parse() - assert_matches_type(SnapPackProgressionsResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -543,7 +543,7 @@ def test_streaming_response_progressions(self, client: PostGrid) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = response.parse() - assert_matches_type(SnapPackProgressionsResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) assert cast(Any, response.is_closed) is True @@ -675,6 +675,7 @@ async def test_method_create_with_all_params_overload_1(self, async_client: Asyn merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) assert_matches_type(SnapPackCreateResponse, snap_pack, path=["response"]) @@ -798,6 +799,7 @@ async def test_method_create_with_all_params_overload_2(self, async_client: Asyn merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) assert_matches_type(SnapPackCreateResponse, snap_pack, path=["response"]) @@ -919,6 +921,7 @@ async def test_method_create_with_all_params_overload_3(self, async_client: Asyn merge_variables={"foo": "bar"}, metadata={"foo": "bar"}, send_date=parse_datetime("2019-12-27T18:11:19.117Z"), + idempotency_key="idempotency-key", ) assert_matches_type(SnapPackCreateResponse, snap_pack, path=["response"]) @@ -976,7 +979,7 @@ async def test_method_retrieve(self, async_client: AsyncPostGrid) -> None: snap_pack = await async_client.print_mail.snap_packs.retrieve( "id", ) - assert_matches_type(SnapPackRetrieveResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -988,7 +991,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncPostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = await response.parse() - assert_matches_type(SnapPackRetrieveResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1000,7 +1003,7 @@ async def test_streaming_response_retrieve(self, async_client: AsyncPostGrid) -> assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = await response.parse() - assert_matches_type(SnapPackRetrieveResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) assert cast(Any, response.is_closed) is True @@ -1016,7 +1019,7 @@ async def test_path_params_retrieve(self, async_client: AsyncPostGrid) -> None: @parametrize async def test_method_list(self, async_client: AsyncPostGrid) -> None: snap_pack = await async_client.print_mail.snap_packs.list() - assert_matches_type(AsyncSkipLimit[SnapPackListResponse], snap_pack, path=["response"]) + assert_matches_type(AsyncSkipLimit[SnapPack], snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1026,7 +1029,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncPostGrid) -> search="search", skip=0, ) - assert_matches_type(AsyncSkipLimit[SnapPackListResponse], snap_pack, path=["response"]) + assert_matches_type(AsyncSkipLimit[SnapPack], snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1036,7 +1039,7 @@ async def test_raw_response_list(self, async_client: AsyncPostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = await response.parse() - assert_matches_type(AsyncSkipLimit[SnapPackListResponse], snap_pack, path=["response"]) + assert_matches_type(AsyncSkipLimit[SnapPack], snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1046,7 +1049,7 @@ async def test_streaming_response_list(self, async_client: AsyncPostGrid) -> Non assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = await response.parse() - assert_matches_type(AsyncSkipLimit[SnapPackListResponse], snap_pack, path=["response"]) + assert_matches_type(AsyncSkipLimit[SnapPack], snap_pack, path=["response"]) assert cast(Any, response.is_closed) is True @@ -1056,7 +1059,7 @@ async def test_method_delete(self, async_client: AsyncPostGrid) -> None: snap_pack = await async_client.print_mail.snap_packs.delete( "id", ) - assert_matches_type(SnapPackDeleteResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1068,7 +1071,7 @@ async def test_raw_response_delete(self, async_client: AsyncPostGrid) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = await response.parse() - assert_matches_type(SnapPackDeleteResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1080,7 +1083,7 @@ async def test_streaming_response_delete(self, async_client: AsyncPostGrid) -> N assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = await response.parse() - assert_matches_type(SnapPackDeleteResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) assert cast(Any, response.is_closed) is True @@ -1098,7 +1101,7 @@ async def test_method_progressions(self, async_client: AsyncPostGrid) -> None: snap_pack = await async_client.print_mail.snap_packs.progressions( "id", ) - assert_matches_type(SnapPackProgressionsResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1110,7 +1113,7 @@ async def test_raw_response_progressions(self, async_client: AsyncPostGrid) -> N assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = await response.parse() - assert_matches_type(SnapPackProgressionsResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) @pytest.mark.skip(reason="Mock server tests are disabled") @parametrize @@ -1122,7 +1125,7 @@ async def test_streaming_response_progressions(self, async_client: AsyncPostGrid assert response.http_request.headers.get("X-Stainless-Lang") == "python" snap_pack = await response.parse() - assert_matches_type(SnapPackProgressionsResponse, snap_pack, path=["response"]) + assert_matches_type(SnapPack, snap_pack, path=["response"]) assert cast(Any, response.is_closed) is True From c64210f898934b14b512b73af9b01640cb30dc66 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Jun 2026 22:09:05 +0000 Subject: [PATCH 7/7] release: 2.3.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 11 +++++++++++ pyproject.toml | 2 +- src/postgrid/_version.py | 2 +- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index bfc26f9..75ec52f 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.2.0" + ".": "2.3.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a9b637..fc9694b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## 2.3.0 (2026-06-12) + +Full Changelog: [v2.2.0...v2.3.0](https://github.com/postgrid/postgrid-python/compare/v2.2.0...v2.3.0) + +### Features + +* **api:** update api with events and webhook capabilities ([6472f0c](https://github.com/postgrid/postgrid-python/commit/6472f0c67cae5d8946f43724d29f53762178918b)) +* New endpoints, fixed and aligned schemas ([c8be87f](https://github.com/postgrid/postgrid-python/commit/c8be87f4cfc054bc31b63e3dd1ab59183664801c)) +* PE-6131 HOTFIX: Fix idempotency key header for create endpoints ([6d2ab69](https://github.com/postgrid/postgrid-python/commit/6d2ab69231ab511d841c2fb914159513d1c64c27)) +* Update available premium paper IDs ([2791811](https://github.com/postgrid/postgrid-python/commit/27918110696bddf2afd84fc854d6a1d7ce139e9a)) + ## 2.2.0 (2026-05-13) Full Changelog: [v2.1.1...v2.2.0](https://github.com/postgrid/postgrid-python/compare/v2.1.1...v2.2.0) diff --git a/pyproject.toml b/pyproject.toml index f4253ad..711fa68 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "postgrid-python" -version = "2.2.0" +version = "2.3.0" description = "The official Python library for the PostGrid API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/postgrid/_version.py b/src/postgrid/_version.py index 4752289..2cb6ce1 100644 --- a/src/postgrid/_version.py +++ b/src/postgrid/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "postgrid" -__version__ = "2.2.0" # x-release-please-version +__version__ = "2.3.0" # x-release-please-version