# How the SDKs are generated

> The SDKs are generated from the API's OpenAPI contract and served by the API itself, so the file you download always matches the API.

Both SDKs are generated from the OpenAPI 3.1 contract of the OpenWAF API, the same one behind the [API reference](https://developers.openwaf.dev/api/). 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.

```sh
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 again
```

Review 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](https://developers.openwaf.dev/api/).
