# Python SDK reference

> The OpenWAF Python client: constructor arguments, method signatures, change options, request, errors and return values.

`openwaf.py` is one module for Python 3.8 or later that uses only the standard library (`urllib`). Download it from `https://dash.openwaf.dev/v1/sdk/openwaf.py` and put it next to your code or on your `PYTHONPATH`.

```py
from openwaf import OpenWAF, OpenWAFError
```

## OpenWAF(token=None, base_url=None, org=None, timeout=60.0)

| Argument | Default |
|---|---|
| `token` | `OPENWAF_TOKEN` |
| `base_url` | `OPENWAF_API_URL`; set it to `https://dash.openwaf.dev` |
| `org` | `OPENWAF_ORG`, else the token's organisation |
| `timeout` | 60 seconds per request |

| Member | Meaning |
|---|---|
| `base_url`, `token`, `timeout` | The values in use. |
| `org_id() -> str` | The organisation the methods use by default (asked once when not configured). |
| `request(method, path, *, …)` | The generic call behind every method (below). |

## Methods

Every API operation is a method named after its operation id in snake_case. All arguments are keyword-only:

```py
owf.list_zones(*, org=None, include=None)
owf.create_record(*, zone, body, reason, org=None, if_match=None, dry_run=None)
owf.revert_zone(*, zone, body, reason, if_match, org=None, dry_run=None)
owf.purge_cache(*, zone, body, org=None, reason=None, dry_run=None)
owf.get_zone_diff(*, zone, org=None, from_=None, to=None)
```

- Path and query parameters are arguments of the same name. A parameter whose name is a Python keyword gets an underscore: `from_`.
- `body` is a `dict` (or a list) sent as JSON.
- Write methods take `reason` (`X-Change-Reason`), `if_match` (`If-Match`, an `int` or `str` version) and `dry_run` (`?dry_run=1`) when their operation supports them; required ones have no default.
- Every method returns the decoded body: a `dict` or `list` for JSON, a `str` for text, `None` for an empty answer.

Commonly used methods:

| Task | Method |
|---|---|
| Zones | `list_zones`, `get_zone`, `create_zone`, `delete_zone` |
| DNS records | `list_records`, `create_record`, `update_record`, `delete_record`, `batch_records` |
| Edge settings and rules | `get_zone_edge`, `update_zone_edge`, `list_rules`, `create_rule`, `delete_rule` |
| History | `list_zone_versions`, `get_zone_version`, `get_zone_diff`, `revert_zone`, `get_zone_propagation` |
| Cache | `purge_cache`, `list_cache_purges` |
| Audit log | `list_audit` |

Each method's docstring gives the operation's summary, its HTTP method and path. The [API reference](https://developers.openwaf.dev/api/) lists every operation.

## request(method, path, *, …)

```py
res = owf.request("GET", "/v1/orgs/%s/zones" % owf.org_id(), query={"include": "merged"})
```

| Argument | Meaning |
|---|---|
| `query` | Query parameters; `None` values are left out, booleans become `true`/`false`. |
| `body`, `content_type` | JSON value, or text/bytes with another `content_type`. |
| `reason`, `if_match`, `dry_run` | Change options. |
| `auth` | `False` sends no token (public routes). |
| `headers` | Extra request headers. |

## OpenWAFError

| Attribute | Meaning |
|---|---|
| `status` | HTTP status; `0` when there was no answer from the API. |
| `code` | API error code, such as `not_found`, `invalid`, `version_conflict`; or `no_token`, `org_unresolved`, `unreachable` for client-side failures. |
| `message` | The message. |
| `field` | The field of a validation error, when given. |
| `body` | The decoded error body, such as `{"current_version": 9, …}`. |

`str(e)` is `code (HTTP status): message`. See [Error handling](https://developers.openwaf.dev/sdk/error-handling/).
