Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "2.2.0"
".": "2.3.0"
}
8 changes: 4 additions & 4 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 119
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/postgrid/postgrid-f236b45c85d9a03ce8a4aa4c457928e4e3d71a1f73a7dda26ec1a3f90b4881f3.yml
openapi_spec_hash: 3562a11137635f5a513f3c1ae8421fda
config_hash: 4429a41bb9161a59679a1a95b1ec7053
configured_endpoints: 137
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/postgrid/postgrid-a1e82d54f9c6456622ef353b6864dd9ccc47c9b5cf6b5fbe98c123f2bdf30f34.yml
openapi_spec_hash: cd682fda35a9733c4bcd508b8d8e6eab
config_hash: f16e8e5b59ab878eee700d0f2dee5645
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
106 changes: 93 additions & 13 deletions api.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
147 changes: 146 additions & 1 deletion src/postgrid/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/postgrid/_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down
2 changes: 1 addition & 1 deletion src/postgrid/_version.py
Original file line number Diff line number Diff line change
@@ -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
14 changes: 14 additions & 0 deletions src/postgrid/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
PrintMailResourceWithStreamingResponse,
AsyncPrintMailResourceWithStreamingResponse,
)
from .bulk_verification import (
BulkVerificationResource,
AsyncBulkVerificationResource,
BulkVerificationResourceWithRawResponse,
AsyncBulkVerificationResourceWithRawResponse,
BulkVerificationResourceWithStreamingResponse,
AsyncBulkVerificationResourceWithStreamingResponse,
)
from .address_verification import (
AddressVerificationResource,
AsyncAddressVerificationResource,
Expand Down Expand Up @@ -38,6 +46,12 @@
"AsyncIntlAddressVerificationResourceWithRawResponse",
"IntlAddressVerificationResourceWithStreamingResponse",
"AsyncIntlAddressVerificationResourceWithStreamingResponse",
"BulkVerificationResource",
"AsyncBulkVerificationResource",
"BulkVerificationResourceWithRawResponse",
"AsyncBulkVerificationResourceWithRawResponse",
"BulkVerificationResourceWithStreamingResponse",
"AsyncBulkVerificationResourceWithStreamingResponse",
"PrintMailResource",
"AsyncPrintMailResource",
"PrintMailResourceWithRawResponse",
Expand Down
14 changes: 12 additions & 2 deletions src/postgrid/resources/address_verification.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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/",
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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/",
Expand Down
Loading
Loading