Why
Manage your entire Woku account from your backend with one typed client:
trackers, VoC tools (NPS/CSAT/CES), wokus, forms, flows, action plans,
support tickets, delivery tracking and survey sends over the public /v1 API.
- Sync and async clients (
Woku/AsyncWoku) on top ofhttpx. - Typed request bodies (Pydantic v2 models generated from the OpenAPI spec) and response shapes.
- Automatic retries with full-jitter backoff and
Retry-Aftersupport. - Idempotent creates: creates carry an auto-generated
Idempotency-Key, so a retry after a blip never creates twice. Action calls (send,test,reply) are never silently replayed. - Auto-paginated lists:
for ticket in woku.tickets.list(): .... - Typed errors with the server
request_idfor support.
Server-only. The secret key grants full management access. Keep it on your backend, never in a browser, mobile app or other client you do not control.
Install
pip install woku
# or: uv add woku
Requires Python 3.9+.
Quickstart
from woku import Woku
woku = Woku(api_key="sk_...") # or set WOKU_API_KEY and call Woku()
# Create a tracker definition (idempotent).
tracker = woku.trackers.create({"name": "Store #1", "system": "retail"})
# Create an NPS tool.
tool = woku.nps_tools.create(
{"name": "Post-purchase", "npsMessage": "How likely are you to recommend us?"}
)
# Tag the NPS tool with the tracker, so every response is grouped by store.
woku.trackers.assign_to_entity(
"nps", tool["_id"], {"name": tracker["name"], "value": "TX-42"}
)
# Send it, then read delivery + response rate.
woku.nps.send_invitations(
{"channel": "email", "npsToolId": tool["_id"], "recipients": ["ana@example.com"]}
)
stats = woku.dispatches.stats({"channel": "email"})
print(stats["responseRate"])
The key is read from WOKU_API_KEY when you omit api_key. You can also pass
it directly: Woku("sk_...").
Request bodies accept either a plain dict (as above) or a generated Pydantic
model from woku._generated.models.
Async
import asyncio
from woku import AsyncWoku
async def main() -> None:
async with AsyncWoku(api_key="sk_...") as woku:
async for ticket in await woku.tickets.list({"severity": "high"}):
print(ticket["title"])
asyncio.run(main())
Pagination
List methods return a page you can iterate item by item across pages, or walk page by page:
for ticket in woku.tickets.list({"severity": "high"}):
print(ticket["title"])
first = woku.dispatches.list({"channel": "whatsapp"})
if first.has_next_page():
second = first.get_next_page()
Errors
Every failure is a WokuError. HTTP errors are typed subclasses carrying the
status, parsed body and request_id:
from woku import NotFoundError, RateLimitError
try:
woku.tickets.get("nonexistent")
except NotFoundError as err:
print(err.status, err.request_id) # 404, "req_..."
except RateLimitError as err:
print("retry after", err.retry_after_seconds)
Transport failures (DNS/TLS/timeout) are WokuConnectionError /
WokuTimeoutError.
Configuration
Woku(
api_key="sk_...",
base_url="https://clientapi.woku.app", # default
timeout=60.0, # seconds, default
max_retries=2, # default
)
Per-call overrides go in the options argument of any method:
woku.tickets.list({"severity": "high"}, options={"timeout": 10.0, "max_retries": 0})
woku.nps_tools.create(body, options={"idempotency_key": "my-key"})
Resources
trackers, nps_tools / csat_tools / ces_tools, nps / csat / ces,
wokus, forms, flows, action_plans, action_plan_groups, tickets,
ticket_destinations, dispatches, reports, company, quarantines.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file woku-0.1.2.tar.gz.
File metadata
- Download URL: woku-0.1.2.tar.gz
- Upload date:
- Size: 40.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.8.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
99a2abb33b5f398291d17d93406b892ab5652b63874a13c6bbcac302ae45ab1a
|
|
| MD5 |
2229103363e0e7a4859ae5ceeffc2655
|
|
| BLAKE2b-256 |
bbe01934ca11d536f0f3172902549ad4318a0949bea86a94726f6b94b459bae0
|
File details
Details for the file woku-0.1.2-py3-none-any.whl.
File metadata
- Download URL: woku-0.1.2-py3-none-any.whl
- Upload date:
- Size: 34.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.8.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1dee527638596e03797dfe7988b596b72d25a8986e1c89dc69897a188a995fc
|
|
| MD5 |
2544db34a57a7057e087d718a6f707bd
|
|
| BLAKE2b-256 |
bcd644dc2f28689f94c3d69230186d4435a5326641396a9e5a7ab8486e6c9e80
|