Both SDKs are generated from the OpenAPI 3.1 contract of the OpenWAF API, the same one behind the API reference. The generator is deterministic: the same contract always produces the same files, and the build fails if the published files fall behind the contract.
Where the files come from
The API serves the files it was built with:
| File | URL | Content type |
|---|---|---|
| TypeScript | https://dash.openwaf.dev/v1/sdk/openwaf.ts | application/typescript |
| Python | https://dash.openwaf.dev/v1/sdk/openwaf.py | text/x-python |
They are public (no token), carry an ETag (If-None-Match answers 304 Not Modified) and may be cached for five minutes. Because they are embedded in the API, the file you download always matches the API that is running. The SDKs are not published to npm or PyPI: you keep the file in your project.
Updates
When the API gains operations or fields, download the file again. The ETag is the first 32 hexadecimal characters of the file's SHA-256, so a script can tell whether your copy is current without downloading it: send it in If-None-Match and a 304 means nothing changed.
ETAG="\"$(shasum -a 256 openwaf.ts | cut -c1-32)\""
curl -sS -o /dev/null -w '%{http_code}\n' -H "If-None-Match: $ETAG" https://dash.openwaf.dev/v1/sdk/openwaf.ts
# 304: up to date · 200: download it againReview the diff before committing it, as you would with any dependency.
What is included
The SDKs expose every operation an API token (owf_…) can call: everything under /v1/orgs/{org}, the call that tells the token's organisation (GET /v1/orgs) and the public origin TLS CA bundles. Left out are sign-in, the MCP endpoint, platform administration, edge-node routes, the SDK downloads themselves and the live event streams (Server-Sent Events, which you read with an EventSource).
Your token's role and scope still apply: a method for an operation your token is not allowed to call fails with 403.
How methods map to operations
| TypeScript | Python | |
|---|---|---|
| Method name | The operation id, such as listZones, createRecord, getZoneDiff | Its snake_case: list_zones, create_record, get_zone_diff |
| Path and query parameters | One object: { zone, limit, before } | Keyword arguments: zone=…, limit=… |
| Request body | body in the same object | body= |
| Change options | Second argument: { reason, ifMatch, dryRun } | Keyword arguments: reason=, if_match=, dry_run= |
org | Optional; defaults to the client's organisation | Same |
| Answer | The decoded JSON body, typed | The decoded JSON body (dict) |
Parameter names that are reserved words get an underscore in Python: the diff's from is from_. Each method's doc comment repeats the operation's summary from the contract (in Spanish) and its HTTP method and path.
The operation ids and their parameters are those of the API reference.