Skip to content
Open
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 @@
{
".": "0.50.0"
".": "0.51.0"
}
6 changes: 3 additions & 3 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 183
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/zavu/zavudev-5d75bbdcac3a0b0a8b798c0b4ef0dacfbc64ad4a20605489dc46dda7c8d1d8d8.yml
openapi_spec_hash: bb242cfd8cc43354412164c2dceae89c
config_hash: 261e1b852ca7f8364e4a283a3edd350a
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/zavu/zavudev-e6e18b26cd123fcd2dcaf3554352c9aa1aa890768d7928fa117382f0b4ca89aa.yml
openapi_spec_hash: 6bc9a1491dec8d8157477abeb4aa8f3c
config_hash: f6a05e2edf2cd1af3f762b8ac759b9a7
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Changelog

## 0.51.0 (2026-09-20)

Full Changelog: [v0.50.0...v0.51.0](https://github.com/zavudev/sdk-python/compare/v0.50.0...v0.51.0)

### Features

* **api:** api update ([5c41bdb](https://github.com/zavudev/sdk-python/commit/5c41bdb53bc1191275bc27bd61357eed594b6f55))
* **api:** api update ([c019637](https://github.com/zavudev/sdk-python/commit/c019637e4c04a7de3cd248bdaaa00d496422c438))
* **api:** api update ([7e1632c](https://github.com/zavudev/sdk-python/commit/7e1632c7d4d94e60e2c83af46641d2681332769a))
* **api:** api update ([7e29fa3](https://github.com/zavudev/sdk-python/commit/7e29fa34b6f63690bab2d73d04640acb39f7027c))
* **api:** api update ([04a0b6d](https://github.com/zavudev/sdk-python/commit/04a0b6dbf002cc4c92180a3ce84cd8c0992ca5d6))
* **api:** api update ([0cf2295](https://github.com/zavudev/sdk-python/commit/0cf22951bce9cb1719aeac4690629d55aa1d3dab))
* **api:** api update ([aab53c7](https://github.com/zavudev/sdk-python/commit/aab53c77cf90c954c9dd644424aa3dccc921480b))
* **api:** api update ([b05594c](https://github.com/zavudev/sdk-python/commit/b05594c35e38a800ccd15ec1eeaa2e833b3ab5c6))
* **api:** api update ([9a3148c](https://github.com/zavudev/sdk-python/commit/9a3148cf7bbf2c9ac183e9c2d90ec8f3c6f4da24))
* **api:** api update ([77c03d9](https://github.com/zavudev/sdk-python/commit/77c03d988890df623ec37dad0c64f96d97ed32b2))

## 0.50.0 (2026-09-08)

Full Changelog: [v0.49.1...v0.50.0](https://github.com/zavudev/sdk-python/compare/v0.49.1...v0.50.0)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "zavudev"
version = "0.50.0"
version = "0.51.0"
description = "The official Python library for the zavudev API"
dynamic = ["readme"]
license = "Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion src/zavudev/_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__ = "zavudev"
__version__ = "0.50.0" # x-release-please-version
__version__ = "0.51.0" # x-release-please-version
58 changes: 38 additions & 20 deletions src/zavudev/resources/addresses.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,27 +48,34 @@ def create(
self,
*,
country_code: str,
first_name: str,
last_name: str,
locality: str,
postal_code: str,
street_address: str,
administrative_area: str | Omit = omit,
business_name: str | Omit = omit,
extended_address: str | Omit = omit,
first_name: str | Omit = omit,
last_name: 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,
) -> AddressCreateResponse:
"""Create a regulatory address for phone number purchases.

Some countries require a
verified address before phone numbers can be activated.
"""
Create a regulatory address, to use as the value of an `address` requirement
when buying a phone number. It is registered for review when it is created, with
status `pending`.

Args:
first_name: First name of the person the address is registered to.

last_name: Last name of the person the address is registered to.

business_name: Business name, when the address belongs to a business. Defaults to the person's
full name.

extra_headers: Send extra headers

extra_query: Add additional query parameters to the request
Expand All @@ -82,14 +89,14 @@ def create(
body=maybe_transform(
{
"country_code": country_code,
"first_name": first_name,
"last_name": last_name,
"locality": locality,
"postal_code": postal_code,
"street_address": street_address,
"administrative_area": administrative_area,
"business_name": business_name,
"extended_address": extended_address,
"first_name": first_name,
"last_name": last_name,
},
address_create_params.AddressCreateParams,
),
Expand Down Expand Up @@ -186,9 +193,11 @@ def delete(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> None:
"""Delete a regulatory address.
"""Delete a regulatory address from this project.

Cannot delete addresses that are in use.
Any address can be deleted,
whatever its status. Phone numbers already purchased with it are not affected,
and neither is information already submitted for later purchases in its country.

Args:
extra_headers: Send extra headers
Expand Down Expand Up @@ -235,27 +244,34 @@ async def create(
self,
*,
country_code: str,
first_name: str,
last_name: str,
locality: str,
postal_code: str,
street_address: str,
administrative_area: str | Omit = omit,
business_name: str | Omit = omit,
extended_address: str | Omit = omit,
first_name: str | Omit = omit,
last_name: 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,
) -> AddressCreateResponse:
"""Create a regulatory address for phone number purchases.

Some countries require a
verified address before phone numbers can be activated.
"""
Create a regulatory address, to use as the value of an `address` requirement
when buying a phone number. It is registered for review when it is created, with
status `pending`.

Args:
first_name: First name of the person the address is registered to.

last_name: Last name of the person the address is registered to.

business_name: Business name, when the address belongs to a business. Defaults to the person's
full name.

extra_headers: Send extra headers

extra_query: Add additional query parameters to the request
Expand All @@ -269,14 +285,14 @@ async def create(
body=await async_maybe_transform(
{
"country_code": country_code,
"first_name": first_name,
"last_name": last_name,
"locality": locality,
"postal_code": postal_code,
"street_address": street_address,
"administrative_area": administrative_area,
"business_name": business_name,
"extended_address": extended_address,
"first_name": first_name,
"last_name": last_name,
},
address_create_params.AddressCreateParams,
),
Expand Down Expand Up @@ -373,9 +389,11 @@ async def delete(
extra_body: Body | None = None,
timeout: float | httpx.Timeout | None | NotGiven = not_given,
) -> None:
"""Delete a regulatory address.
"""Delete a regulatory address from this project.

Cannot delete addresses that are in use.
Any address can be deleted,
whatever its status. Phone numbers already purchased with it are not affected,
and neither is information already submitted for later purchases in its country.

Args:
extra_headers: Send extra headers
Expand Down
58 changes: 28 additions & 30 deletions src/zavudev/resources/broadcasts/broadcasts.py
Original file line number Diff line number Diff line change
Expand Up @@ -516,17 +516,11 @@ def send(
"""
Start sending the broadcast immediately or schedule for later.

**The account must be past the unverified level to send, except on WhatsApp.**
An account that has verified nothing is refused with `403` and code
`kyc_required` on every channel other than `whatsapp`. Any one of these lifts
it: identity verification (KYC), a saved payment method, a settled deposit, or a
paid plan. Business verification (KYB) is not required to broadcast; it gates
10DLC registration only. A `whatsapp` broadcast is exempt: it can only be built
on a template, and Meta vets the business and the content when it approves that
template, so an unapproved template is refused instead. `smart` is not exempt,
since it can route a contact to SMS or email. Drafts can be created, edited and
kept without any check. Every send path (dashboard, API and CLI) enforces the
same rule.
**Sending a broadcast needs no account verification.** Identity and business
verification raise daily ceilings; neither is a permission to broadcast, on any
channel. What stands in front of a broadcast is the content review below, and it
applies to every send path — dashboard, API and CLI. Drafts can be created,
edited and kept freely.

**Daily ceilings apply per recipient.** Each message a broadcast sends counts
against the channel's daily ceiling (see `POST /v1/messages`). Once the ceiling
Expand All @@ -536,10 +530,15 @@ def send(
**Review depends on the channel, and cannot be bypassed.** A draft is submitted
to automated content review here; it does not go straight out. A WhatsApp
broadcast built on a Meta-approved template skips review (Meta already vetted
the content) and begins sending. An email broadcast sends as soon as the
automated review passes. Every other channel moves to `pending_admin_review` and
waits for a person. If the review rejects it, use PATCH to edit the content then
call POST /retry-review.
the content) and begins sending. An email broadcast sends as soon as the review
passes it, unless the review asks for a person. Every other channel moves to
`pending_admin_review` and waits for a person. A broadcast the review refuses
lands on `rejected`: use PATCH to edit the content then call POST /retry-review,
or escalate it for a manual review.

A broadcast is read once, on its own text, rather than per recipient. While an
account's sending is suspended its recipients fail individually with `errorCode`
`SENDING_SUSPENDED`; see `POST /v1/messages`.

Calling this on a broadcast that is already `approved` or `scheduled` sends or
reschedules it directly, since it has already been reviewed. Reserves the
Expand Down Expand Up @@ -1031,17 +1030,11 @@ async def send(
"""
Start sending the broadcast immediately or schedule for later.

**The account must be past the unverified level to send, except on WhatsApp.**
An account that has verified nothing is refused with `403` and code
`kyc_required` on every channel other than `whatsapp`. Any one of these lifts
it: identity verification (KYC), a saved payment method, a settled deposit, or a
paid plan. Business verification (KYB) is not required to broadcast; it gates
10DLC registration only. A `whatsapp` broadcast is exempt: it can only be built
on a template, and Meta vets the business and the content when it approves that
template, so an unapproved template is refused instead. `smart` is not exempt,
since it can route a contact to SMS or email. Drafts can be created, edited and
kept without any check. Every send path (dashboard, API and CLI) enforces the
same rule.
**Sending a broadcast needs no account verification.** Identity and business
verification raise daily ceilings; neither is a permission to broadcast, on any
channel. What stands in front of a broadcast is the content review below, and it
applies to every send path — dashboard, API and CLI. Drafts can be created,
edited and kept freely.

**Daily ceilings apply per recipient.** Each message a broadcast sends counts
against the channel's daily ceiling (see `POST /v1/messages`). Once the ceiling
Expand All @@ -1051,10 +1044,15 @@ async def send(
**Review depends on the channel, and cannot be bypassed.** A draft is submitted
to automated content review here; it does not go straight out. A WhatsApp
broadcast built on a Meta-approved template skips review (Meta already vetted
the content) and begins sending. An email broadcast sends as soon as the
automated review passes. Every other channel moves to `pending_admin_review` and
waits for a person. If the review rejects it, use PATCH to edit the content then
call POST /retry-review.
the content) and begins sending. An email broadcast sends as soon as the review
passes it, unless the review asks for a person. Every other channel moves to
`pending_admin_review` and waits for a person. A broadcast the review refuses
lands on `rejected`: use PATCH to edit the content then call POST /retry-review,
or escalate it for a manual review.

A broadcast is read once, on its own text, rather than per recipient. While an
account's sending is suspended its recipients fail individually with `errorCode`
`SENDING_SUSPENDED`; see `POST /v1/messages`.

Calling this on a broadcast that is already `approved` or `scheduled` sends or
reschedules it directly, since it has already been reviewed. Reserves the
Expand Down
20 changes: 20 additions & 0 deletions src/zavudev/resources/broadcasts/contacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ def list(
Args:
status: Status of a contact within a broadcast.

- `pending`, `queued`, `sending`: not handed to the provider yet.
- `sent`: accepted by the provider; delivery is not confirmed yet. Channels that
never report delivery leave the recipient here.
- `delivered`: the channel confirmed delivery to the device. A WhatsApp read
receipt also counts as delivered.
- `failed`: not delivered. A recipient can move from `sent` or `delivered` to
`failed` when the provider reports a failure late.
- `skipped`: not sent, because the recipient opted out of the channel or the
broadcast was cancelled before reaching it.

extra_headers: Send extra headers

extra_query: Add additional query parameters to the request
Expand Down Expand Up @@ -215,6 +225,16 @@ def list(
Args:
status: Status of a contact within a broadcast.

- `pending`, `queued`, `sending`: not handed to the provider yet.
- `sent`: accepted by the provider; delivery is not confirmed yet. Channels that
never report delivery leave the recipient here.
- `delivered`: the channel confirmed delivery to the device. A WhatsApp read
receipt also counts as delivered.
- `failed`: not delivered. A recipient can move from `sent` or `delivered` to
`failed` when the provider reports a failure late.
- `skipped`: not sent, because the recipient opted out of the channel or the
broadcast was cancelled before reaching it.

extra_headers: Send extra headers

extra_query: Add additional query parameters to the request
Expand Down
38 changes: 20 additions & 18 deletions src/zavudev/resources/calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,16 @@ def create(
**Requirements:**

- The Voice Agents feature must be enabled for your team (otherwise `403`).
- An account that has verified nothing may only call the phone numbers the
project has verified (`403` with code `destination_not_verified`, and
`details.verifiedNumbers` lists them), and at most 5 calls a day (`429` with
code `daily_limit_exceeded`). A number is verified from the dashboard's
Sandbox screen by sending the pre-filled WhatsApp message from that phone; the
same verification covers SMS and calls. Verify your identity, add a payment
method, settle a deposit or subscribe to call any destination. That raises the
ceiling to 50 calls a day on Free; paid plans have no daily call ceiling. Full
reference: https://docs.zavu.dev/concepts/sending-limits
- An account may call any destination from its first minute, within the daily
ceiling: 5 calls a day for an account that has verified nothing, 50 a day on
Free once it has verified its identity, added a payment method, settled a
deposit or subscribed. Paid plans have no daily call ceiling. Over it, `429`
with code `daily_limit_exceeded`. Full reference:
https://docs.zavu.dev/concepts/sending-limits
- The call is read by Zavu's automated risk review before it is dialed, the way
a message is (see `POST /v1/messages`). A call is never held for a person: one
the review stops is failed rather than placed late. Repeated refusals suspend
the account's calling, answered with `403` and code `sending_suspended`.
- The sender's agent must have `voice.enabled` set to `true`.
- Not available with test-mode API keys.

Expand Down Expand Up @@ -315,15 +316,16 @@ async def create(
**Requirements:**

- The Voice Agents feature must be enabled for your team (otherwise `403`).
- An account that has verified nothing may only call the phone numbers the
project has verified (`403` with code `destination_not_verified`, and
`details.verifiedNumbers` lists them), and at most 5 calls a day (`429` with
code `daily_limit_exceeded`). A number is verified from the dashboard's
Sandbox screen by sending the pre-filled WhatsApp message from that phone; the
same verification covers SMS and calls. Verify your identity, add a payment
method, settle a deposit or subscribe to call any destination. That raises the
ceiling to 50 calls a day on Free; paid plans have no daily call ceiling. Full
reference: https://docs.zavu.dev/concepts/sending-limits
- An account may call any destination from its first minute, within the daily
ceiling: 5 calls a day for an account that has verified nothing, 50 a day on
Free once it has verified its identity, added a payment method, settled a
deposit or subscribed. Paid plans have no daily call ceiling. Over it, `429`
with code `daily_limit_exceeded`. Full reference:
https://docs.zavu.dev/concepts/sending-limits
- The call is read by Zavu's automated risk review before it is dialed, the way
a message is (see `POST /v1/messages`). A call is never held for a person: one
the review stops is failed rather than placed late. Repeated refusals suspend
the account's calling, answered with `403` and code `sending_suspended`.
- The sender's agent must have `voice.enabled` set to `true`.
- Not available with test-mode API keys.

Expand Down
Loading
Loading