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