whatsapp-cloud-api-py 0.1.1__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/PKG-INFO +19 -11
  2. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/README.md +18 -10
  3. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/pyproject.toml +1 -1
  4. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/client.py +3 -3
  5. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_client.py +5 -5
  6. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_messages_resource.py +1 -1
  7. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_resources_flows.py +1 -1
  8. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_resources_media.py +2 -2
  9. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_resources_phone_numbers.py +1 -1
  10. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_resources_templates.py +1 -1
  11. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/.github/workflows/publish.yml +0 -0
  12. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/.gitignore +0 -0
  13. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/LICENSE +0 -0
  14. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/__init__.py +0 -0
  15. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/errors/__init__.py +0 -0
  16. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/errors/categorize.py +0 -0
  17. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/errors/graph_api_error.py +0 -0
  18. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/errors/retry.py +0 -0
  19. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/events/__init__.py +0 -0
  20. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/events/dispatcher.py +0 -0
  21. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/events/events.py +0 -0
  22. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/resources/__init__.py +0 -0
  23. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/resources/flows.py +0 -0
  24. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/resources/media.py +0 -0
  25. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/resources/messages/__init__.py +0 -0
  26. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/resources/messages/models.py +0 -0
  27. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/resources/messages/resource.py +0 -0
  28. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/resources/phone_numbers.py +0 -0
  29. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/resources/templates/__init__.py +0 -0
  30. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/resources/templates/models.py +0 -0
  31. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/resources/templates/resource.py +0 -0
  32. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/types.py +0 -0
  33. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/utils/__init__.py +0 -0
  34. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/utils/case.py +0 -0
  35. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/webhooks/__init__.py +0 -0
  36. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/webhooks/normalize.py +0 -0
  37. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/src/whatsapp_cloud_api/webhooks/verify.py +0 -0
  38. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/__init__.py +0 -0
  39. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/conftest.py +0 -0
  40. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_errors_categorize.py +0 -0
  41. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_errors_graph_api_error.py +0 -0
  42. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_errors_retry.py +0 -0
  43. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_events.py +0 -0
  44. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_events_dispatcher.py +0 -0
  45. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_messages_models.py +0 -0
  46. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_types.py +0 -0
  47. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_utils_case.py +0 -0
  48. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_webhooks_normalize.py +0 -0
  49. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/tests/test_webhooks_verify.py +0 -0
  50. {whatsapp_cloud_api_py-0.1.1 → whatsapp_cloud_api_py-0.2.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: whatsapp-cloud-api-py
3
- Version: 0.1.1
3
+ Version: 0.2.0
4
4
  Summary: Async Python SDK for WhatsApp Business Cloud API with Pydantic V2
5
5
  Project-URL: Homepage, https://github.com/HeiCg/whatsapp-cloud-api-py
6
6
  Project-URL: Repository, https://github.com/HeiCg/whatsapp-cloud-api-py
@@ -26,12 +26,22 @@ Description-Content-Type: text/markdown
26
26
 
27
27
  # whatsapp-cloud-api-py
28
28
 
29
- Community-built async Python SDK for the WhatsApp Business Cloud API.
29
+ Community-built async Python SDK for the WhatsApp Business Cloud API, powered by [Kapso](https://kapso.ai).
30
30
 
31
31
  > **Note:** This is an **independent Python implementation** — not a port or fork. It was inspired by the excellent [`@kapso/whatsapp-cloud-api`](https://github.com/gokapso/whatsapp-cloud-api-js) (TypeScript), but written from scratch in Python with its own architecture, design choices, and API surface.
32
32
 
33
33
  Built with **httpx** (HTTP/2 + connection pooling), **Pydantic V2** (Rust-powered validation), and optional **pyventus** event-driven webhooks.
34
34
 
35
+ ## Prerequisites
36
+
37
+ This SDK connects to Meta's WhatsApp Cloud API through [Kapso's](https://kapso.ai) managed proxy. You'll need a **Kapso API key** before getting started:
38
+
39
+ 1. Create an account at [kapso.ai](https://kapso.ai)
40
+ 2. Connect your WhatsApp Business account
41
+ 3. Generate an API key from the dashboard
42
+
43
+ See the [Kapso docs](https://docs.kapso.ai/docs/introduction) for detailed setup instructions.
44
+
35
45
  ## Features
36
46
 
37
47
  - **Fully async** — all I/O uses `async`/`await` with httpx
@@ -69,7 +79,7 @@ import asyncio
69
79
  from whatsapp_cloud_api import WhatsAppClient, TextMessage
70
80
 
71
81
  async def main():
72
- async with WhatsAppClient(access_token="YOUR_TOKEN") as client:
82
+ async with WhatsAppClient(access_token="YOUR_KAPSO_API_KEY") as client:
73
83
  response = await client.messages.send_text(TextMessage(
74
84
  phone_number_id="PHONE_NUMBER_ID",
75
85
  to="5511999999999",
@@ -562,24 +572,22 @@ except GraphApiError as e:
562
572
  ```python
563
573
  from whatsapp_cloud_api import WhatsAppClient
564
574
 
565
- # Default: graph.facebook.com, v23.0, HTTP/2, 30s timeout
566
- client = WhatsAppClient(access_token="TOKEN")
575
+ # Default: api.kapso.ai, v23.0, HTTP/2, 30s timeout
576
+ client = WhatsAppClient(access_token="YOUR_KAPSO_API_KEY")
567
577
 
568
- # Custom configuration
578
+ # Custom timeout
569
579
  client = WhatsAppClient(
570
- access_token="TOKEN",
571
- base_url="https://graph.facebook.com",
572
- graph_version="v23.0",
580
+ access_token="YOUR_KAPSO_API_KEY",
573
581
  timeout=60.0,
574
582
  )
575
583
 
576
584
  # Bring your own httpx client
577
585
  import httpx
578
586
  custom_http = httpx.AsyncClient(http2=True, timeout=60.0)
579
- client = WhatsAppClient(access_token="TOKEN", http_client=custom_http)
587
+ client = WhatsAppClient(access_token="YOUR_KAPSO_API_KEY", http_client=custom_http)
580
588
 
581
589
  # Always use as async context manager
582
- async with WhatsAppClient(access_token="TOKEN") as client:
590
+ async with WhatsAppClient(access_token="YOUR_KAPSO_API_KEY") as client:
583
591
  await client.messages.send_text(...)
584
592
  ```
585
593
 
@@ -1,11 +1,21 @@
1
1
  # whatsapp-cloud-api-py
2
2
 
3
- Community-built async Python SDK for the WhatsApp Business Cloud API.
3
+ Community-built async Python SDK for the WhatsApp Business Cloud API, powered by [Kapso](https://kapso.ai).
4
4
 
5
5
  > **Note:** This is an **independent Python implementation** — not a port or fork. It was inspired by the excellent [`@kapso/whatsapp-cloud-api`](https://github.com/gokapso/whatsapp-cloud-api-js) (TypeScript), but written from scratch in Python with its own architecture, design choices, and API surface.
6
6
 
7
7
  Built with **httpx** (HTTP/2 + connection pooling), **Pydantic V2** (Rust-powered validation), and optional **pyventus** event-driven webhooks.
8
8
 
9
+ ## Prerequisites
10
+
11
+ This SDK connects to Meta's WhatsApp Cloud API through [Kapso's](https://kapso.ai) managed proxy. You'll need a **Kapso API key** before getting started:
12
+
13
+ 1. Create an account at [kapso.ai](https://kapso.ai)
14
+ 2. Connect your WhatsApp Business account
15
+ 3. Generate an API key from the dashboard
16
+
17
+ See the [Kapso docs](https://docs.kapso.ai/docs/introduction) for detailed setup instructions.
18
+
9
19
  ## Features
10
20
 
11
21
  - **Fully async** — all I/O uses `async`/`await` with httpx
@@ -43,7 +53,7 @@ import asyncio
43
53
  from whatsapp_cloud_api import WhatsAppClient, TextMessage
44
54
 
45
55
  async def main():
46
- async with WhatsAppClient(access_token="YOUR_TOKEN") as client:
56
+ async with WhatsAppClient(access_token="YOUR_KAPSO_API_KEY") as client:
47
57
  response = await client.messages.send_text(TextMessage(
48
58
  phone_number_id="PHONE_NUMBER_ID",
49
59
  to="5511999999999",
@@ -536,24 +546,22 @@ except GraphApiError as e:
536
546
  ```python
537
547
  from whatsapp_cloud_api import WhatsAppClient
538
548
 
539
- # Default: graph.facebook.com, v23.0, HTTP/2, 30s timeout
540
- client = WhatsAppClient(access_token="TOKEN")
549
+ # Default: api.kapso.ai, v23.0, HTTP/2, 30s timeout
550
+ client = WhatsAppClient(access_token="YOUR_KAPSO_API_KEY")
541
551
 
542
- # Custom configuration
552
+ # Custom timeout
543
553
  client = WhatsAppClient(
544
- access_token="TOKEN",
545
- base_url="https://graph.facebook.com",
546
- graph_version="v23.0",
554
+ access_token="YOUR_KAPSO_API_KEY",
547
555
  timeout=60.0,
548
556
  )
549
557
 
550
558
  # Bring your own httpx client
551
559
  import httpx
552
560
  custom_http = httpx.AsyncClient(http2=True, timeout=60.0)
553
- client = WhatsAppClient(access_token="TOKEN", http_client=custom_http)
561
+ client = WhatsAppClient(access_token="YOUR_KAPSO_API_KEY", http_client=custom_http)
554
562
 
555
563
  # Always use as async context manager
556
- async with WhatsAppClient(access_token="TOKEN") as client:
564
+ async with WhatsAppClient(access_token="YOUR_KAPSO_API_KEY") as client:
557
565
  await client.messages.send_text(...)
558
566
  ```
559
567
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "whatsapp-cloud-api-py"
3
- version = "0.1.1"
3
+ version = "0.2.0"
4
4
  description = "Async Python SDK for WhatsApp Business Cloud API with Pydantic V2"
5
5
  requires-python = ">=3.11"
6
6
  license = "MIT"
@@ -15,8 +15,8 @@ if TYPE_CHECKING:
15
15
  from .resources.phone_numbers import PhoneNumbersResource
16
16
  from .resources.templates.resource import TemplatesResource
17
17
 
18
- _DEFAULT_BASE_URL = "https://graph.facebook.com"
19
- _DEFAULT_VERSION = "v23.0"
18
+ _DEFAULT_BASE_URL = "https://api.kapso.ai/meta/whatsapp"
19
+ _DEFAULT_VERSION = "v24.0"
20
20
 
21
21
 
22
22
  class WhatsAppClient:
@@ -71,7 +71,7 @@ class WhatsAppClient:
71
71
 
72
72
  @property
73
73
  def _auth_headers(self) -> dict[str, str]:
74
- return {"Authorization": f"Bearer {self._access_token}"}
74
+ return {"X-API-Key": self._access_token}
75
75
 
76
76
  # ── core request ─────────────────────────────────────────────
77
77
 
@@ -9,7 +9,7 @@ import respx
9
9
  from whatsapp_cloud_api.client import WhatsAppClient
10
10
  from whatsapp_cloud_api.errors import GraphApiError
11
11
 
12
- BASE = "https://graph.facebook.com/v23.0"
12
+ BASE = "https://api.kapso.ai/meta/whatsapp/v24.0"
13
13
 
14
14
 
15
15
  class TestUrl:
@@ -28,11 +28,11 @@ class TestUrl:
28
28
 
29
29
  def test_custom_base_url(self):
30
30
  client = WhatsAppClient(access_token="tok", base_url="https://custom.api.com/")
31
- assert client._url("path") == "https://custom.api.com/v23.0/path"
31
+ assert client._url("path") == "https://custom.api.com/v24.0/path"
32
32
 
33
33
  def test_custom_version(self):
34
34
  client = WhatsAppClient(access_token="tok", graph_version="v22.0")
35
- assert client._url("path") == "https://graph.facebook.com/v22.0/path"
35
+ assert client._url("path") == "https://api.kapso.ai/meta/whatsapp/v22.0/path"
36
36
 
37
37
 
38
38
  class TestRequest:
@@ -78,7 +78,7 @@ class TestRequest:
78
78
  )
79
79
  async with WhatsAppClient(access_token="my-token") as client:
80
80
  await client.get("test")
81
- assert route.calls[0].request.headers["authorization"] == "Bearer my-token"
81
+ assert route.calls[0].request.headers["x-api-key"] == "my-token"
82
82
 
83
83
  @respx.mock
84
84
  async def test_post_with_json(self):
@@ -163,7 +163,7 @@ class TestFetchMethods:
163
163
  async with WhatsAppClient(access_token="secret-tok") as client:
164
164
  resp = await client.fetch_authenticated(url)
165
165
  assert resp.content == b"bytes"
166
- assert route.calls[0].request.headers["authorization"] == "Bearer secret-tok"
166
+ assert route.calls[0].request.headers["x-api-key"] == "secret-tok"
167
167
 
168
168
 
169
169
  class TestCachedProperties:
@@ -22,7 +22,7 @@ from whatsapp_cloud_api.resources.messages.models import (
22
22
  )
23
23
  from whatsapp_cloud_api.resources.messages.resource import MessagesResource
24
24
 
25
- BASE = "https://graph.facebook.com/v23.0"
25
+ BASE = "https://api.kapso.ai/meta/whatsapp/v24.0"
26
26
  PHONE = "1234567890"
27
27
  MSG_URL = f"{BASE}/{PHONE}/messages"
28
28
 
@@ -14,7 +14,7 @@ from whatsapp_cloud_api.resources.flows import (
14
14
  UpdateFlowAssetInput,
15
15
  )
16
16
 
17
- BASE = "https://graph.facebook.com/v23.0"
17
+ BASE = "https://api.kapso.ai/meta/whatsapp/v24.0"
18
18
  WABA = "waba123"
19
19
 
20
20
 
@@ -8,7 +8,7 @@ import respx
8
8
  from whatsapp_cloud_api.client import WhatsAppClient
9
9
  from whatsapp_cloud_api.resources.media import MediaResource, MediaUploadInput
10
10
 
11
- BASE = "https://graph.facebook.com/v23.0"
11
+ BASE = "https://api.kapso.ai/meta/whatsapp/v24.0"
12
12
 
13
13
 
14
14
  class TestUpload:
@@ -155,4 +155,4 @@ class TestDownload:
155
155
  assert data == b"auth-bytes"
156
156
  # With use_auth=True, the first call already has auth headers
157
157
  req = cdn_route.calls[0].request
158
- assert "Bearer tok" in req.headers.get("authorization", "")
158
+ assert req.headers.get("x-api-key") == "tok"
@@ -17,7 +17,7 @@ from whatsapp_cloud_api.resources.phone_numbers import (
17
17
  VerifyCodeInput,
18
18
  )
19
19
 
20
- BASE = "https://graph.facebook.com/v23.0"
20
+ BASE = "https://api.kapso.ai/meta/whatsapp/v24.0"
21
21
  PHONE = "1234567890"
22
22
 
23
23
 
@@ -15,7 +15,7 @@ from whatsapp_cloud_api.resources.templates.models import (
15
15
  )
16
16
  from whatsapp_cloud_api.resources.templates.resource import TemplatesResource
17
17
 
18
- BASE = "https://graph.facebook.com/v23.0"
18
+ BASE = "https://api.kapso.ai/meta/whatsapp/v24.0"
19
19
  WABA = "waba123"
20
20
 
21
21