Metadata-Version: 2.5
Name: deewan
Version: 0.2.1
Summary: Official Python SDK for the Deewan video meetings API: rooms, join links, media tokens, participants, meetings, webinars, polls, breakout rooms, recordings and signed webhooks.
Project-URL: Homepage, https://deewan.io
Project-URL: Documentation, https://deewan.io/en/docs/sdk#python
Project-URL: API reference, https://deewan.io/en/docs/reference
Author-email: Deewan <support@deewan.io>
License-Expression: MIT
License-File: LICENSE
Keywords: api,arabic,deewan,e2ee,sdk,video,video-meetings,webhooks,webinars,webrtc
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Communications :: Conferencing
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.9
Provides-Extra: recordings
Requires-Dist: cryptography>=42; extra == 'recordings'
Description-Content-Type: text/markdown

# deewan

[![PyPI](https://img.shields.io/pypi/v/deewan.svg)](https://pypi.org/project/deewan/)
[![Python](https://img.shields.io/pypi/pyversions/deewan.svg)](https://pypi.org/project/deewan/)

The official Python SDK for [Deewan](https://deewan.io): video meetings built for the
Middle East and North Africa, in Arabic and English, end-to-end encrypted.

Create rooms, send people into meetings, schedule them, moderate them, run webinars,
polls and breakout rooms, fetch recordings, and verify webhooks — from Django, FastAPI,
Flask or any Python 3.9+ backend. Typed, and no dependencies.

```bash
pip install deewan
pip install "deewan[recordings]"   # only if you download (decrypt) recordings on your server
```

## Quick start

```python
import os
from deewan import Deewan

deewan = Deewan(os.environ["DEEWAN_API_KEY"])

room = deewan.rooms.create(name="Onboarding call", settings={"admission": "knock"})

link = deewan.rooms.create_join_link(
    room["id"],
    name="Sara Ahmed",
    role="host",
    user_id="user_123",  # your own id: the same person keeps the same identity
)
print(link["url"])  # send it to Sara, or embed it in an <iframe>
```

Get an API key in the Deewan dashboard under **Developers**. Keys are server secrets:
never send one to a browser or a mobile app.

## Your own interface

```python
# A media token for one person; return the whole response to your web or mobile app,
# where @deewanio/client, @deewanio/react-native or the deewan Flutter package joins with it.
token = deewan.rooms.create_token(room["id"], name="Omar", user_id="user_456")

# Strict end-to-end encrypted rooms: the client SDK makes the participant's exchange key.
token = deewan.rooms.create_token(room["id"], name="Omar", exchange_key=key_from_their_device)
```

## Everything the API does

| Area | Methods |
|---|---|
| Account | `me()` |
| Rooms | `rooms.list()` · `rooms.all()` · `create()` · `retrieve()` · `update()` · `delete()` · `end()` |
| Joining | `rooms.create_join_link()` · `rooms.create_token()` |
| Participants | `rooms.list_participants()` · `mute_participant()` · `remove_participant()` · `make_cohost()` · `remove_cohost()` |
| Waiting room | `rooms.list_waiting()` · `admit()` · `deny()` |
| Webinars | `rooms.invite_to_speak()` · `rooms.move_to_audience()` |
| Scheduled meetings | `meetings.list()` · `create()` · `retrieve()` · `update()` · `cancel()` |
| Polls | `polls.list()` · `create()` · `close()` · `reopen()` · `delete()` |
| Breakout rooms | `breakouts.get()` · `start()` · `move()` · `add_room()` · `rename_room()` · `remove_room()` · `announce()` · `end()` |
| Recordings | `recordings.list()` · `retrieve()` · `download_info()` · `download()` · `delete()` |
| Webhooks | `webhooks.list()` · `create()` · `update()` · `delete()` · `test()` · `deliveries()` |
| Verifying webhooks | `verify_webhook(raw_body, signature_header, secret)` |

```python
# Webinars, polls and breakout rooms
webinar = deewan.rooms.create(name="Product launch", settings={"type": "webinar"})
deewan.polls.create(room["id"], question="Ship it?", options=["Yes", "Not yet"], results="after_vote")
deewan.breakouts.start(room["id"], rooms=["Design", "Engineering"], assign="auto", duration_seconds=900)

for r in deewan.rooms.all():   # every room, page by page
    print(r["name"])
```

## Webhooks

```python
from deewan import verify_webhook

# Pass the raw request body, exactly as received (e.g. request.body in Django).
event = verify_webhook(raw_body, headers["Deewan-Signature"], os.environ["DEEWAN_WEBHOOK_SECRET"])
if event["type"] == "recording.ready":
    ...
```

Signatures are HMAC-SHA-256, compared in constant time, and refused when older than
five minutes, so a captured request can't be replayed.

## Errors, retries and timeouts

Every failure raises `DeewanError` with `status`, `code` (e.g. `not_found`,
`rate_limited`, `insufficient_scope`), `message` and the `request_id` to quote to support.

```python
deewan = Deewan(api_key, timeout=15.0, max_retries=2)
```

Reads are retried on 429 and 5xx with backoff; writes are retried only when they can't
have been applied, so nothing happens twice.

## Security

- Requests go only over HTTPS, and redirects are refused, so your key is only ever sent to Deewan.
- Use the narrowest scopes: a service that only sends people into rooms needs `rooms:read` and `tokens:create`.
- Issue one join link or token per person, after your app has checked they may join.

## Links

- Documentation: https://deewan.io/en/docs
- API reference and OpenAPI 3.1: https://deewan.io/en/docs/reference
- Support: support@deewan.io

MIT © Deewan
