> ## Documentation Index
> Fetch the complete documentation index at: https://woku.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK de Python

> Gestiona toda tu cuenta de woku desde tu backend con el paquete woku: cliente sync y async sobre httpx para trackers, herramientas VoC, tickets, planes de accion y envios de la API v1

<Info>
  **Disponible en el plan Corporate.** Esta funcionalidad forma parte de las capacidades empresariales de woku. [Conversa con nuestro equipo comercial](https://woku.app/pricing).
</Info>

El paquete **`woku`** es el cliente oficial **de servidor** para la API de
gestion de woku en Python. Con un cliente síncrono (`Woku`) y su gemelo
asíncrono (`AsyncWoku`) sobre `httpx` administras trackers externos,
herramientas VoC (**NPS**, **CSAT**, **CES**), wokus, formularios, flows,
planes de accion, tickets de soporte, envios de encuestas y seguimiento de
entrega, todo sobre la API pública **v1**. Es la contraparte del
[SDK de JavaScript](/docs/development/sdk-javascript), con la misma superficie.

<Warning>
  Es un SDK **de servidor**. La clave secreta de compañía otorga acceso completo
  de gestion, asi que debe vivir solo en tu backend. Nunca la incluyas en un
  cliente que no controles. Para capturar feedback desde una app móvil usa el
  [SDK de React Native](/docs/development/sdk-react-native), que usa una clave pública
  de captura.
</Warning>

## Instalación

```bash theme={null}
pip install woku
```

Requiere Python 3.9 o superior. El SDK trae `py.typed`, asi que los type
checkers reconocen sus tipos sin configuración extra.

## Inicialización

Crea una instancia de `Woku` una sola vez y reutilízala.

```python theme={null}
from woku import Woku

woku = Woku(api_key="sk_...")  # o define WOKU_API_KEY y llama Woku()
```

Si omites `api_key`, el SDK lee la variable de entorno `WOKU_API_KEY`.

| Opción        | Requerida | Descripción                                                        |
| ------------- | --------- | ------------------------------------------------------------------ |
| `api_key`     | sí        | Clave secreta de compañía. Por defecto la variable `WOKU_API_KEY`. |
| `base_url`    | no        | URL base de la API. Por defecto `https://clientapi.woku.app`.      |
| `timeout`     | no        | Tiempo máximo por solicitud en segundos. Por defecto `60.0`.       |
| `max_retries` | no        | Reintentos automáticos ante fallos transitorios. Por defecto `2`.  |

Los cuerpos de solicitud aceptan un diccionario simple (como en los ejemplos) o
un modelo Pydantic generado desde `woku._generated.models`.

## Autenticación

El SDK autentica con la **Clave de Compañía**, la misma clave secreta que usa
la [API](/docs/development/api). La obtiene el propietario de la empresa desde la
sección **Información** de la empresa en la aplicación administrativa:
[admin.woku.app](https://admin.woku.app).

### Rotar o revocar la clave

Rotar genera una clave nueva e **invalida de inmediato la anterior**; guarda la
que devuelve antes de continuar.

```python theme={null}
result = woku.company.rotate_key()
# guarda result["secretKey"] de forma segura; la clave anterior deja de funcionar

woku.company.revoke_key()  # deja la cuenta sin clave activa
```

## Quickstart

Un flujo completo: crear un tracker, crear una herramienta NPS, enviarla y leer
la tasa de respuesta.

```python theme={null}
from woku import Woku

woku = Woku(api_key="sk_...")

# 1. Crear una definición de tracker (idempotente).
tracker = woku.trackers.create({"name": "Tienda #1", "system": "retail"})

# 2. Crear una herramienta NPS y enviarla por correo o WhatsApp.
tool = woku.nps_tools.create(
    {"name": "Post-compra", "npsMessage": "¿Qué tan probable es que nos recomiendes?"}
)
woku.nps.send_invitations(
    {"channel": "email", "npsToolId": tool["_id"], "recipients": ["ana@example.com"]}
)

# 3. Leer la entrega y la tasa de respuesta.
stats = woku.dispatches.stats({"channel": "email"})
print(stats["responseRate"])
```

## Cliente asíncrono

`AsyncWoku` expone los mismos recursos con métodos `await` e iteración con
`async for`. Úsalo como context manager para cerrar el pool de conexiones.

```python theme={null}
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())
```

## Flujos principales

### Tickets de soporte

Los tickets los genera la IA de woku. Puedes listarlos, filtrarlos y curarlos.

```python theme={null}
for ticket in woku.tickets.list({"severity": "high"}):
    print(ticket["title"])

stats = woku.tickets.stats()
```

### Planes de acción

```python theme={null}
woku.action_plans.approve("plan_123")
woku.action_plans.send(
    "plan_123",
    {"provider": "jira", "target": {"projectId": "10032", "issueTypeId": "10001"}},
)
```

## Paginación

Los métodos de listado devuelven una página iterable. Recorre cada elemento a
través de las páginas, o página por página:

```python theme={null}
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()
```

En el cliente asíncrono se recorre con `async for`.

## Idempotencia

Los `create` incluyen automáticamente una `Idempotency-Key`, asi que un
reintento tras un fallo transitorio nunca crea dos veces. Las acciones (enviar,
probar, responder) **no** se reintentan solas. Puedes pasar tu propia clave por
llamada con el argumento `options`.

## Manejo de errores

Cada fallo es un `WokuError`. Los errores HTTP son subclases tipadas que llevan
el `status`, el cuerpo y el `request_id` del servidor:

```python theme={null}
from woku import NotFoundError, RateLimitError

try:
    woku.tickets.get("inexistente")
except NotFoundError as err:
    print(err.status, err.request_id)  # 404, "req_..."
except RateLimitError as err:
    print("reintenta en", err.retry_after_seconds)
```

Los fallos de transporte (DNS, TLS, timeout) son `WokuConnectionError` y
`WokuTimeoutError`. El SDK reintenta automáticamente los GET y las escrituras
idempotentes con backoff y respeto del header `Retry-After`.

## Configuración por llamada

Cada método acepta overrides en el argumento `options`:

```python theme={null}
woku.tickets.list({"severity": "high"}, options={"timeout": 10.0, "max_retries": 0})
woku.nps_tools.create(body, options={"idempotency_key": "mi-clave"})
```

## Recursos

`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`.

## Versionado

El SDK sigue **versionado semántico** (`MAJOR.MINOR.PATCH`). La versión actual
publicada es la **`0.1.0`**. Te recomendamos fijar un rango compatible (por
ejemplo `>=0.1,<0.2`) y revisar el changelog antes de subir de versión MAJOR.
Las versiones y sus notas están en
[PyPI](https://pypi.org/project/woku/) y en los
[releases de GitHub](https://github.com/wokuApp/woku-python/releases).

## Recursos

* **Paquete PyPI:** [woku](https://pypi.org/project/woku/)
* **Código y ejemplos:** [github.com/wokuApp/woku-python](https://github.com/wokuApp/woku-python)
* **SDK de JavaScript equivalente:** [SDK de JavaScript](/docs/development/sdk-javascript)
* **Referencia de la API:** [Guía de Integración API](/docs/development/api)
