diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index a713055..d52d2b9 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.12.0"
+ ".": "0.13.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 2a2bfcd..76f728e 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 37
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/zavu%2Fzavudev-064fa598a02a9f8529186ca4292253201abbc550c98ed1d2c44dd637e4977cba.yml
-openapi_spec_hash: 76468e579e64c10eda3ce647c38482a6
-config_hash: 2c81a5597d0125c8a91faaddaadb8b9e
+configured_endpoints: 40
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/zavu%2Fzavudev-632d79d39ef49ea571930f3e1c71d63145b23905126df2957d4eb61a309e9054.yml
+openapi_spec_hash: 74d14877ffe27741c222a83646071717
+config_hash: ab9d47848e436f9b6b787afd062ff9a7
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ba04902..8a230e2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# Changelog
+## 0.13.0 (2025-12-17)
+
+Full Changelog: [v0.12.0...v0.13.0](https://github.com/zavudev/sdk-python/compare/v0.12.0...v0.13.0)
+
+### Features
+
+* **api:** api update ([1f7ee8c](https://github.com/zavudev/sdk-python/commit/1f7ee8ce8cf2a6a3cb662bdddba1279ca916d1d1))
+* **api:** whatsapp profile ([beb8348](https://github.com/zavudev/sdk-python/commit/beb834894c1b86c9bfe69783ad4ebb0648e3b7d6))
+
## 0.12.0 (2025-12-16)
Full Changelog: [v0.11.0...v0.12.0](https://github.com/zavudev/sdk-python/compare/v0.11.0...v0.12.0)
diff --git a/api.md b/api.md
index 632c0c8..6052289 100644
--- a/api.md
+++ b/api.md
@@ -41,7 +41,17 @@ Methods:
Types:
```python
-from zavudev.types import Sender, SenderWebhook, WebhookEvent, WebhookSecretResponse
+from zavudev.types import (
+ Sender,
+ SenderWebhook,
+ WebhookEvent,
+ WebhookSecretResponse,
+ WhatsappBusinessProfile,
+ WhatsappBusinessProfileResponse,
+ WhatsappBusinessProfileVertical,
+ SenderUpdateProfileResponse,
+ SenderUploadProfilePictureResponse,
+)
```
Methods:
@@ -51,7 +61,10 @@ Methods:
- client.senders.update(sender_id, \*\*params) -> Sender
- client.senders.list(\*\*params) -> SyncCursor[Sender]
- client.senders.delete(sender_id) -> None
+- client.senders.get_profile(sender_id) -> WhatsappBusinessProfileResponse
- client.senders.regenerate_webhook_secret(sender_id) -> WebhookSecretResponse
+- client.senders.update_profile(sender_id, \*\*params) -> SenderUpdateProfileResponse
+- client.senders.upload_profile_picture(sender_id, \*\*params) -> SenderUploadProfilePictureResponse
# Contacts
diff --git a/pyproject.toml b/pyproject.toml
index 2524838..73a7d11 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "zavudev"
-version = "0.12.0"
+version = "0.13.0"
description = "The official Python library for the zavudev API"
dynamic = ["readme"]
license = "Apache-2.0"
diff --git a/src/zavudev/_version.py b/src/zavudev/_version.py
index 06e8856..646a67a 100644
--- a/src/zavudev/_version.py
+++ b/src/zavudev/_version.py
@@ -1,4 +1,4 @@
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
__title__ = "zavudev"
-__version__ = "0.12.0" # x-release-please-version
+__version__ = "0.13.0" # x-release-please-version
diff --git a/src/zavudev/resources/senders.py b/src/zavudev/resources/senders.py
index 10d881a..227c0ab 100644
--- a/src/zavudev/resources/senders.py
+++ b/src/zavudev/resources/senders.py
@@ -3,11 +3,19 @@
from __future__ import annotations
from typing import List, Optional
+from typing_extensions import Literal
import httpx
-from ..types import sender_list_params, sender_create_params, sender_update_params
-from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, omit, not_given
+from ..types import (
+ WhatsappBusinessProfileVertical,
+ sender_list_params,
+ sender_create_params,
+ sender_update_params,
+ sender_update_profile_params,
+ sender_upload_profile_picture_params,
+)
+from .._types import Body, Omit, Query, Headers, NoneType, NotGiven, SequenceNotStr, omit, not_given
from .._utils import maybe_transform, async_maybe_transform
from .._compat import cached_property
from .._resource import SyncAPIResource, AsyncAPIResource
@@ -22,6 +30,10 @@
from ..types.sender import Sender
from ..types.webhook_event import WebhookEvent
from ..types.webhook_secret_response import WebhookSecretResponse
+from ..types.sender_update_profile_response import SenderUpdateProfileResponse
+from ..types.whatsapp_business_profile_response import WhatsappBusinessProfileResponse
+from ..types.whatsapp_business_profile_vertical import WhatsappBusinessProfileVertical
+from ..types.sender_upload_profile_picture_response import SenderUploadProfilePictureResponse
__all__ = ["SendersResource", "AsyncSendersResource"]
@@ -259,6 +271,41 @@ def delete(
cast_to=NoneType,
)
+ def get_profile(
+ self,
+ sender_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,
+ ) -> WhatsappBusinessProfileResponse:
+ """Get the WhatsApp Business profile for a sender.
+
+ The sender must have a WhatsApp
+ Business Account connected.
+
+ 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 sender_id:
+ raise ValueError(f"Expected a non-empty value for `sender_id` but received {sender_id!r}")
+ return self._get(
+ f"/v1/senders/{sender_id}/profile",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=WhatsappBusinessProfileResponse,
+ )
+
def regenerate_webhook_secret(
self,
sender_id: str,
@@ -294,6 +341,118 @@ def regenerate_webhook_secret(
cast_to=WebhookSecretResponse,
)
+ def update_profile(
+ self,
+ sender_id: str,
+ *,
+ about: str | Omit = omit,
+ address: str | Omit = omit,
+ description: str | Omit = omit,
+ email: str | Omit = omit,
+ vertical: WhatsappBusinessProfileVertical | Omit = omit,
+ websites: SequenceNotStr[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,
+ ) -> SenderUpdateProfileResponse:
+ """Update the WhatsApp Business profile for a sender.
+
+ The sender must have a
+ WhatsApp Business Account connected.
+
+ Args:
+ about: Short description of the business (max 139 characters).
+
+ address: Physical address of the business (max 256 characters).
+
+ description: Extended description of the business (max 512 characters).
+
+ email: Business email address.
+
+ vertical: Business category for WhatsApp Business profile.
+
+ websites: Business website URLs (maximum 2).
+
+ 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 sender_id:
+ raise ValueError(f"Expected a non-empty value for `sender_id` but received {sender_id!r}")
+ return self._patch(
+ f"/v1/senders/{sender_id}/profile",
+ body=maybe_transform(
+ {
+ "about": about,
+ "address": address,
+ "description": description,
+ "email": email,
+ "vertical": vertical,
+ "websites": websites,
+ },
+ sender_update_profile_params.SenderUpdateProfileParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SenderUpdateProfileResponse,
+ )
+
+ def upload_profile_picture(
+ self,
+ sender_id: str,
+ *,
+ image_url: str,
+ mime_type: Literal["image/jpeg", "image/png"],
+ # 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,
+ ) -> SenderUploadProfilePictureResponse:
+ """Upload a new profile picture for the WhatsApp Business profile.
+
+ The image will
+ be uploaded to Meta and set as the profile picture.
+
+ Args:
+ image_url: URL of the image to upload.
+
+ mime_type: MIME type of the image.
+
+ 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 sender_id:
+ raise ValueError(f"Expected a non-empty value for `sender_id` but received {sender_id!r}")
+ return self._post(
+ f"/v1/senders/{sender_id}/profile/picture",
+ body=maybe_transform(
+ {
+ "image_url": image_url,
+ "mime_type": mime_type,
+ },
+ sender_upload_profile_picture_params.SenderUploadProfilePictureParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SenderUploadProfilePictureResponse,
+ )
+
class AsyncSendersResource(AsyncAPIResource):
@cached_property
@@ -528,6 +687,41 @@ async def delete(
cast_to=NoneType,
)
+ async def get_profile(
+ self,
+ sender_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,
+ ) -> WhatsappBusinessProfileResponse:
+ """Get the WhatsApp Business profile for a sender.
+
+ The sender must have a WhatsApp
+ Business Account connected.
+
+ 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 sender_id:
+ raise ValueError(f"Expected a non-empty value for `sender_id` but received {sender_id!r}")
+ return await self._get(
+ f"/v1/senders/{sender_id}/profile",
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=WhatsappBusinessProfileResponse,
+ )
+
async def regenerate_webhook_secret(
self,
sender_id: str,
@@ -563,6 +757,118 @@ async def regenerate_webhook_secret(
cast_to=WebhookSecretResponse,
)
+ async def update_profile(
+ self,
+ sender_id: str,
+ *,
+ about: str | Omit = omit,
+ address: str | Omit = omit,
+ description: str | Omit = omit,
+ email: str | Omit = omit,
+ vertical: WhatsappBusinessProfileVertical | Omit = omit,
+ websites: SequenceNotStr[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,
+ ) -> SenderUpdateProfileResponse:
+ """Update the WhatsApp Business profile for a sender.
+
+ The sender must have a
+ WhatsApp Business Account connected.
+
+ Args:
+ about: Short description of the business (max 139 characters).
+
+ address: Physical address of the business (max 256 characters).
+
+ description: Extended description of the business (max 512 characters).
+
+ email: Business email address.
+
+ vertical: Business category for WhatsApp Business profile.
+
+ websites: Business website URLs (maximum 2).
+
+ 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 sender_id:
+ raise ValueError(f"Expected a non-empty value for `sender_id` but received {sender_id!r}")
+ return await self._patch(
+ f"/v1/senders/{sender_id}/profile",
+ body=await async_maybe_transform(
+ {
+ "about": about,
+ "address": address,
+ "description": description,
+ "email": email,
+ "vertical": vertical,
+ "websites": websites,
+ },
+ sender_update_profile_params.SenderUpdateProfileParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SenderUpdateProfileResponse,
+ )
+
+ async def upload_profile_picture(
+ self,
+ sender_id: str,
+ *,
+ image_url: str,
+ mime_type: Literal["image/jpeg", "image/png"],
+ # 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,
+ ) -> SenderUploadProfilePictureResponse:
+ """Upload a new profile picture for the WhatsApp Business profile.
+
+ The image will
+ be uploaded to Meta and set as the profile picture.
+
+ Args:
+ image_url: URL of the image to upload.
+
+ mime_type: MIME type of the image.
+
+ 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 sender_id:
+ raise ValueError(f"Expected a non-empty value for `sender_id` but received {sender_id!r}")
+ return await self._post(
+ f"/v1/senders/{sender_id}/profile/picture",
+ body=await async_maybe_transform(
+ {
+ "image_url": image_url,
+ "mime_type": mime_type,
+ },
+ sender_upload_profile_picture_params.SenderUploadProfilePictureParams,
+ ),
+ options=make_request_options(
+ extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
+ ),
+ cast_to=SenderUploadProfilePictureResponse,
+ )
+
class SendersResourceWithRawResponse:
def __init__(self, senders: SendersResource) -> None:
@@ -583,9 +889,18 @@ def __init__(self, senders: SendersResource) -> None:
self.delete = to_raw_response_wrapper(
senders.delete,
)
+ self.get_profile = to_raw_response_wrapper(
+ senders.get_profile,
+ )
self.regenerate_webhook_secret = to_raw_response_wrapper(
senders.regenerate_webhook_secret,
)
+ self.update_profile = to_raw_response_wrapper(
+ senders.update_profile,
+ )
+ self.upload_profile_picture = to_raw_response_wrapper(
+ senders.upload_profile_picture,
+ )
class AsyncSendersResourceWithRawResponse:
@@ -607,9 +922,18 @@ def __init__(self, senders: AsyncSendersResource) -> None:
self.delete = async_to_raw_response_wrapper(
senders.delete,
)
+ self.get_profile = async_to_raw_response_wrapper(
+ senders.get_profile,
+ )
self.regenerate_webhook_secret = async_to_raw_response_wrapper(
senders.regenerate_webhook_secret,
)
+ self.update_profile = async_to_raw_response_wrapper(
+ senders.update_profile,
+ )
+ self.upload_profile_picture = async_to_raw_response_wrapper(
+ senders.upload_profile_picture,
+ )
class SendersResourceWithStreamingResponse:
@@ -631,9 +955,18 @@ def __init__(self, senders: SendersResource) -> None:
self.delete = to_streamed_response_wrapper(
senders.delete,
)
+ self.get_profile = to_streamed_response_wrapper(
+ senders.get_profile,
+ )
self.regenerate_webhook_secret = to_streamed_response_wrapper(
senders.regenerate_webhook_secret,
)
+ self.update_profile = to_streamed_response_wrapper(
+ senders.update_profile,
+ )
+ self.upload_profile_picture = to_streamed_response_wrapper(
+ senders.upload_profile_picture,
+ )
class AsyncSendersResourceWithStreamingResponse:
@@ -655,6 +988,15 @@ def __init__(self, senders: AsyncSendersResource) -> None:
self.delete = async_to_streamed_response_wrapper(
senders.delete,
)
+ self.get_profile = async_to_streamed_response_wrapper(
+ senders.get_profile,
+ )
self.regenerate_webhook_secret = async_to_streamed_response_wrapper(
senders.regenerate_webhook_secret,
)
+ self.update_profile = async_to_streamed_response_wrapper(
+ senders.update_profile,
+ )
+ self.upload_profile_picture = async_to_streamed_response_wrapper(
+ senders.upload_profile_picture,
+ )
diff --git a/src/zavudev/types/__init__.py b/src/zavudev/types/__init__.py
index 619a18a..7585c0e 100644
--- a/src/zavudev/types/__init__.py
+++ b/src/zavudev/types/__init__.py
@@ -52,16 +52,25 @@
from .broadcast_create_response import BroadcastCreateResponse as BroadcastCreateResponse
from .broadcast_update_response import BroadcastUpdateResponse as BroadcastUpdateResponse
from .phone_number_capabilities import PhoneNumberCapabilities as PhoneNumberCapabilities
+from .whatsapp_business_profile import WhatsappBusinessProfile as WhatsappBusinessProfile
from .owned_phone_number_pricing import OwnedPhoneNumberPricing as OwnedPhoneNumberPricing
from .phone_number_update_params import PhoneNumberUpdateParams as PhoneNumberUpdateParams
from .broadcast_retrieve_response import BroadcastRetrieveResponse as BroadcastRetrieveResponse
from .phone_number_purchase_params import PhoneNumberPurchaseParams as PhoneNumberPurchaseParams
from .phone_number_update_response import PhoneNumberUpdateResponse as PhoneNumberUpdateResponse
+from .sender_update_profile_params import SenderUpdateProfileParams as SenderUpdateProfileParams
from .phone_number_purchase_response import PhoneNumberPurchaseResponse as PhoneNumberPurchaseResponse
from .phone_number_retrieve_response import PhoneNumberRetrieveResponse as PhoneNumberRetrieveResponse
+from .sender_update_profile_response import SenderUpdateProfileResponse as SenderUpdateProfileResponse
from .introspect_validate_phone_params import IntrospectValidatePhoneParams as IntrospectValidatePhoneParams
from .introspect_validate_phone_response import IntrospectValidatePhoneResponse as IntrospectValidatePhoneResponse
+from .whatsapp_business_profile_response import WhatsappBusinessProfileResponse as WhatsappBusinessProfileResponse
+from .whatsapp_business_profile_vertical import WhatsappBusinessProfileVertical as WhatsappBusinessProfileVertical
from .phone_number_search_available_params import PhoneNumberSearchAvailableParams as PhoneNumberSearchAvailableParams
+from .sender_upload_profile_picture_params import SenderUploadProfilePictureParams as SenderUploadProfilePictureParams
from .phone_number_search_available_response import (
PhoneNumberSearchAvailableResponse as PhoneNumberSearchAvailableResponse,
)
+from .sender_upload_profile_picture_response import (
+ SenderUploadProfilePictureResponse as SenderUploadProfilePictureResponse,
+)
diff --git a/src/zavudev/types/sender.py b/src/zavudev/types/sender.py
index 8dd927e..4863684 100644
--- a/src/zavudev/types/sender.py
+++ b/src/zavudev/types/sender.py
@@ -8,7 +8,36 @@
from .._models import BaseModel
from .sender_webhook import SenderWebhook
-__all__ = ["Sender"]
+__all__ = ["Sender", "Whatsapp", "WhatsappPaymentStatus"]
+
+
+class WhatsappPaymentStatus(BaseModel):
+ """Payment configuration status from Meta."""
+
+ can_send_templates: Optional[bool] = FieldInfo(alias="canSendTemplates", default=None)
+ """Whether template messages can be sent.
+
+ Requires setupStatus=COMPLETE and methodStatus=VALID.
+ """
+
+ method_status: Optional[str] = FieldInfo(alias="methodStatus", default=None)
+ """Payment method status (VALID, NONE, etc.)."""
+
+ setup_status: Optional[str] = FieldInfo(alias="setupStatus", default=None)
+ """Payment setup status (COMPLETE, NOT_STARTED, etc.)."""
+
+
+class Whatsapp(BaseModel):
+ """WhatsApp Business Account information. Only present if a WABA is connected."""
+
+ display_phone_number: Optional[str] = FieldInfo(alias="displayPhoneNumber", default=None)
+ """Display phone number."""
+
+ payment_status: Optional[WhatsappPaymentStatus] = FieldInfo(alias="paymentStatus", default=None)
+ """Payment configuration status from Meta."""
+
+ phone_number_id: Optional[str] = FieldInfo(alias="phoneNumberId", default=None)
+ """WhatsApp phone number ID from Meta."""
class Sender(BaseModel):
@@ -28,3 +57,6 @@ class Sender(BaseModel):
webhook: Optional[SenderWebhook] = None
"""Webhook configuration for the sender."""
+
+ whatsapp: Optional[Whatsapp] = None
+ """WhatsApp Business Account information. Only present if a WABA is connected."""
diff --git a/src/zavudev/types/sender_update_profile_params.py b/src/zavudev/types/sender_update_profile_params.py
new file mode 100644
index 0000000..30f344f
--- /dev/null
+++ b/src/zavudev/types/sender_update_profile_params.py
@@ -0,0 +1,30 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import TypedDict
+
+from .._types import SequenceNotStr
+from .whatsapp_business_profile_vertical import WhatsappBusinessProfileVertical
+
+__all__ = ["SenderUpdateProfileParams"]
+
+
+class SenderUpdateProfileParams(TypedDict, total=False):
+ about: str
+ """Short description of the business (max 139 characters)."""
+
+ address: str
+ """Physical address of the business (max 256 characters)."""
+
+ description: str
+ """Extended description of the business (max 512 characters)."""
+
+ email: str
+ """Business email address."""
+
+ vertical: WhatsappBusinessProfileVertical
+ """Business category for WhatsApp Business profile."""
+
+ websites: SequenceNotStr[str]
+ """Business website URLs (maximum 2)."""
diff --git a/src/zavudev/types/sender_update_profile_response.py b/src/zavudev/types/sender_update_profile_response.py
new file mode 100644
index 0000000..7af0b04
--- /dev/null
+++ b/src/zavudev/types/sender_update_profile_response.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+from .whatsapp_business_profile import WhatsappBusinessProfile
+
+__all__ = ["SenderUpdateProfileResponse"]
+
+
+class SenderUpdateProfileResponse(BaseModel):
+ profile: WhatsappBusinessProfile
+ """WhatsApp Business profile information."""
+
+ success: bool
diff --git a/src/zavudev/types/sender_upload_profile_picture_params.py b/src/zavudev/types/sender_upload_profile_picture_params.py
new file mode 100644
index 0000000..a32dc0b
--- /dev/null
+++ b/src/zavudev/types/sender_upload_profile_picture_params.py
@@ -0,0 +1,17 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from __future__ import annotations
+
+from typing_extensions import Literal, Required, Annotated, TypedDict
+
+from .._utils import PropertyInfo
+
+__all__ = ["SenderUploadProfilePictureParams"]
+
+
+class SenderUploadProfilePictureParams(TypedDict, total=False):
+ image_url: Required[Annotated[str, PropertyInfo(alias="imageUrl")]]
+ """URL of the image to upload."""
+
+ mime_type: Required[Annotated[Literal["image/jpeg", "image/png"], PropertyInfo(alias="mimeType")]]
+ """MIME type of the image."""
diff --git a/src/zavudev/types/sender_upload_profile_picture_response.py b/src/zavudev/types/sender_upload_profile_picture_response.py
new file mode 100644
index 0000000..bc30cf7
--- /dev/null
+++ b/src/zavudev/types/sender_upload_profile_picture_response.py
@@ -0,0 +1,13 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+from .whatsapp_business_profile import WhatsappBusinessProfile
+
+__all__ = ["SenderUploadProfilePictureResponse"]
+
+
+class SenderUploadProfilePictureResponse(BaseModel):
+ profile: WhatsappBusinessProfile
+ """WhatsApp Business profile information."""
+
+ success: bool
diff --git a/src/zavudev/types/whatsapp_business_profile.py b/src/zavudev/types/whatsapp_business_profile.py
new file mode 100644
index 0000000..cfe7b49
--- /dev/null
+++ b/src/zavudev/types/whatsapp_business_profile.py
@@ -0,0 +1,35 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing import List, Optional
+
+from pydantic import Field as FieldInfo
+
+from .._models import BaseModel
+from .whatsapp_business_profile_vertical import WhatsappBusinessProfileVertical
+
+__all__ = ["WhatsappBusinessProfile"]
+
+
+class WhatsappBusinessProfile(BaseModel):
+ """WhatsApp Business profile information."""
+
+ about: Optional[str] = None
+ """Short description of the business (max 139 characters)."""
+
+ address: Optional[str] = None
+ """Physical address of the business (max 256 characters)."""
+
+ description: Optional[str] = None
+ """Extended description of the business (max 512 characters)."""
+
+ email: Optional[str] = None
+ """Business email address."""
+
+ profile_picture_url: Optional[str] = FieldInfo(alias="profilePictureUrl", default=None)
+ """URL of the business profile picture."""
+
+ vertical: Optional[WhatsappBusinessProfileVertical] = None
+ """Business category for WhatsApp Business profile."""
+
+ websites: Optional[List[str]] = None
+ """Business website URLs (maximum 2)."""
diff --git a/src/zavudev/types/whatsapp_business_profile_response.py b/src/zavudev/types/whatsapp_business_profile_response.py
new file mode 100644
index 0000000..40a2aae
--- /dev/null
+++ b/src/zavudev/types/whatsapp_business_profile_response.py
@@ -0,0 +1,11 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from .._models import BaseModel
+from .whatsapp_business_profile import WhatsappBusinessProfile
+
+__all__ = ["WhatsappBusinessProfileResponse"]
+
+
+class WhatsappBusinessProfileResponse(BaseModel):
+ profile: WhatsappBusinessProfile
+ """WhatsApp Business profile information."""
diff --git a/src/zavudev/types/whatsapp_business_profile_vertical.py b/src/zavudev/types/whatsapp_business_profile_vertical.py
new file mode 100644
index 0000000..61a6478
--- /dev/null
+++ b/src/zavudev/types/whatsapp_business_profile_vertical.py
@@ -0,0 +1,27 @@
+# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+from typing_extensions import Literal, TypeAlias
+
+__all__ = ["WhatsappBusinessProfileVertical"]
+
+WhatsappBusinessProfileVertical: TypeAlias = Literal[
+ "UNDEFINED",
+ "OTHER",
+ "AUTO",
+ "BEAUTY",
+ "APPAREL",
+ "EDU",
+ "ENTERTAIN",
+ "EVENT_PLAN",
+ "FINANCE",
+ "GROCERY",
+ "GOVT",
+ "HOTEL",
+ "HEALTH",
+ "NONPROFIT",
+ "PROF_SERVICES",
+ "RETAIL",
+ "TRAVEL",
+ "RESTAURANT",
+ "NOT_A_BIZ",
+]
diff --git a/tests/api_resources/test_senders.py b/tests/api_resources/test_senders.py
index 5811de8..2e0e3cb 100644
--- a/tests/api_resources/test_senders.py
+++ b/tests/api_resources/test_senders.py
@@ -9,7 +9,13 @@
from zavudev import Zavudev, AsyncZavudev
from tests.utils import assert_matches_type
-from zavudev.types import Sender, WebhookSecretResponse
+from zavudev.types import (
+ Sender,
+ WebhookSecretResponse,
+ SenderUpdateProfileResponse,
+ WhatsappBusinessProfileResponse,
+ SenderUploadProfilePictureResponse,
+)
from zavudev.pagination import SyncCursor, AsyncCursor
base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010")
@@ -243,6 +249,48 @@ def test_path_params_delete(self, client: Zavudev) -> None:
"",
)
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_get_profile(self, client: Zavudev) -> None:
+ sender = client.senders.get_profile(
+ "senderId",
+ )
+ assert_matches_type(WhatsappBusinessProfileResponse, sender, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_get_profile(self, client: Zavudev) -> None:
+ response = client.senders.with_raw_response.get_profile(
+ "senderId",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ sender = response.parse()
+ assert_matches_type(WhatsappBusinessProfileResponse, sender, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_get_profile(self, client: Zavudev) -> None:
+ with client.senders.with_streaming_response.get_profile(
+ "senderId",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ sender = response.parse()
+ assert_matches_type(WhatsappBusinessProfileResponse, sender, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_get_profile(self, client: Zavudev) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `sender_id` but received ''"):
+ client.senders.with_raw_response.get_profile(
+ "",
+ )
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
def test_method_regenerate_webhook_secret(self, client: Zavudev) -> None:
@@ -285,6 +333,112 @@ def test_path_params_regenerate_webhook_secret(self, client: Zavudev) -> None:
"",
)
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_update_profile(self, client: Zavudev) -> None:
+ sender = client.senders.update_profile(
+ sender_id="senderId",
+ )
+ assert_matches_type(SenderUpdateProfileResponse, sender, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_update_profile_with_all_params(self, client: Zavudev) -> None:
+ sender = client.senders.update_profile(
+ sender_id="senderId",
+ about="Succulent specialists!",
+ address="address",
+ description="We specialize in providing high-quality succulents.",
+ email="contact@example.com",
+ vertical="RETAIL",
+ websites=["https://www.example.com"],
+ )
+ assert_matches_type(SenderUpdateProfileResponse, sender, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_update_profile(self, client: Zavudev) -> None:
+ response = client.senders.with_raw_response.update_profile(
+ sender_id="senderId",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ sender = response.parse()
+ assert_matches_type(SenderUpdateProfileResponse, sender, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_update_profile(self, client: Zavudev) -> None:
+ with client.senders.with_streaming_response.update_profile(
+ sender_id="senderId",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ sender = response.parse()
+ assert_matches_type(SenderUpdateProfileResponse, sender, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_update_profile(self, client: Zavudev) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `sender_id` but received ''"):
+ client.senders.with_raw_response.update_profile(
+ sender_id="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_method_upload_profile_picture(self, client: Zavudev) -> None:
+ sender = client.senders.upload_profile_picture(
+ sender_id="senderId",
+ image_url="https://example.com/profile.jpg",
+ mime_type="image/jpeg",
+ )
+ assert_matches_type(SenderUploadProfilePictureResponse, sender, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_raw_response_upload_profile_picture(self, client: Zavudev) -> None:
+ response = client.senders.with_raw_response.upload_profile_picture(
+ sender_id="senderId",
+ image_url="https://example.com/profile.jpg",
+ mime_type="image/jpeg",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ sender = response.parse()
+ assert_matches_type(SenderUploadProfilePictureResponse, sender, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_streaming_response_upload_profile_picture(self, client: Zavudev) -> None:
+ with client.senders.with_streaming_response.upload_profile_picture(
+ sender_id="senderId",
+ image_url="https://example.com/profile.jpg",
+ mime_type="image/jpeg",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ sender = response.parse()
+ assert_matches_type(SenderUploadProfilePictureResponse, sender, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ def test_path_params_upload_profile_picture(self, client: Zavudev) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `sender_id` but received ''"):
+ client.senders.with_raw_response.upload_profile_picture(
+ sender_id="",
+ image_url="https://example.com/profile.jpg",
+ mime_type="image/jpeg",
+ )
+
class TestAsyncSenders:
parametrize = pytest.mark.parametrize(
@@ -516,6 +670,48 @@ async def test_path_params_delete(self, async_client: AsyncZavudev) -> None:
"",
)
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_get_profile(self, async_client: AsyncZavudev) -> None:
+ sender = await async_client.senders.get_profile(
+ "senderId",
+ )
+ assert_matches_type(WhatsappBusinessProfileResponse, sender, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_get_profile(self, async_client: AsyncZavudev) -> None:
+ response = await async_client.senders.with_raw_response.get_profile(
+ "senderId",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ sender = await response.parse()
+ assert_matches_type(WhatsappBusinessProfileResponse, sender, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_get_profile(self, async_client: AsyncZavudev) -> None:
+ async with async_client.senders.with_streaming_response.get_profile(
+ "senderId",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ sender = await response.parse()
+ assert_matches_type(WhatsappBusinessProfileResponse, sender, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_get_profile(self, async_client: AsyncZavudev) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `sender_id` but received ''"):
+ await async_client.senders.with_raw_response.get_profile(
+ "",
+ )
+
@pytest.mark.skip(reason="Prism tests are disabled")
@parametrize
async def test_method_regenerate_webhook_secret(self, async_client: AsyncZavudev) -> None:
@@ -557,3 +753,109 @@ async def test_path_params_regenerate_webhook_secret(self, async_client: AsyncZa
await async_client.senders.with_raw_response.regenerate_webhook_secret(
"",
)
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_update_profile(self, async_client: AsyncZavudev) -> None:
+ sender = await async_client.senders.update_profile(
+ sender_id="senderId",
+ )
+ assert_matches_type(SenderUpdateProfileResponse, sender, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_update_profile_with_all_params(self, async_client: AsyncZavudev) -> None:
+ sender = await async_client.senders.update_profile(
+ sender_id="senderId",
+ about="Succulent specialists!",
+ address="address",
+ description="We specialize in providing high-quality succulents.",
+ email="contact@example.com",
+ vertical="RETAIL",
+ websites=["https://www.example.com"],
+ )
+ assert_matches_type(SenderUpdateProfileResponse, sender, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_update_profile(self, async_client: AsyncZavudev) -> None:
+ response = await async_client.senders.with_raw_response.update_profile(
+ sender_id="senderId",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ sender = await response.parse()
+ assert_matches_type(SenderUpdateProfileResponse, sender, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_update_profile(self, async_client: AsyncZavudev) -> None:
+ async with async_client.senders.with_streaming_response.update_profile(
+ sender_id="senderId",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ sender = await response.parse()
+ assert_matches_type(SenderUpdateProfileResponse, sender, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_update_profile(self, async_client: AsyncZavudev) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `sender_id` but received ''"):
+ await async_client.senders.with_raw_response.update_profile(
+ sender_id="",
+ )
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_method_upload_profile_picture(self, async_client: AsyncZavudev) -> None:
+ sender = await async_client.senders.upload_profile_picture(
+ sender_id="senderId",
+ image_url="https://example.com/profile.jpg",
+ mime_type="image/jpeg",
+ )
+ assert_matches_type(SenderUploadProfilePictureResponse, sender, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_raw_response_upload_profile_picture(self, async_client: AsyncZavudev) -> None:
+ response = await async_client.senders.with_raw_response.upload_profile_picture(
+ sender_id="senderId",
+ image_url="https://example.com/profile.jpg",
+ mime_type="image/jpeg",
+ )
+
+ assert response.is_closed is True
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+ sender = await response.parse()
+ assert_matches_type(SenderUploadProfilePictureResponse, sender, path=["response"])
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_streaming_response_upload_profile_picture(self, async_client: AsyncZavudev) -> None:
+ async with async_client.senders.with_streaming_response.upload_profile_picture(
+ sender_id="senderId",
+ image_url="https://example.com/profile.jpg",
+ mime_type="image/jpeg",
+ ) as response:
+ assert not response.is_closed
+ assert response.http_request.headers.get("X-Stainless-Lang") == "python"
+
+ sender = await response.parse()
+ assert_matches_type(SenderUploadProfilePictureResponse, sender, path=["response"])
+
+ assert cast(Any, response.is_closed) is True
+
+ @pytest.mark.skip(reason="Prism tests are disabled")
+ @parametrize
+ async def test_path_params_upload_profile_picture(self, async_client: AsyncZavudev) -> None:
+ with pytest.raises(ValueError, match=r"Expected a non-empty value for `sender_id` but received ''"):
+ await async_client.senders.with_raw_response.upload_profile_picture(
+ sender_id="",
+ image_url="https://example.com/profile.jpg",
+ mime_type="image/jpeg",
+ )