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

# SDKs

> Planned, not shipped. Until then, the API is small enough to call directly — and here is how.

> [!WARNING]
>
> **Not available yet.** `wardendb` for Python and `@wardendb/sdk` for TypeScript appear in earlier design documents and are not published. Anything you read about them describes intent. Use the HTTP API or [the MCP server](https://warden.buildlab.in/offerings/mcp-server.md) today.

The data plane is one `POST` and three `GET`s, so a usable client is short. Both examples below do the thing that actually matters: **treat every status as an outcome to reason about, not an exception to swallow.**

```python Python theme={null}
import os, requests

GATEWAY = "http://127.0.0.1:9470"
HEADERS = {"Authorization": f"Bearer {os.environ['WARDEN_API_KEY']}"}

def execute(statement, params=None, *, reason, idempotency_key=None, mode=None):
    body = {"statement": statement, "params": params or [], "reason": reason}
    if idempotency_key:
        body["idempotency_key"] = idempotency_key
    if mode:
        body["mode"] = mode
    r = requests.post(f"{GATEWAY}/api/v1/gateway/execute", json=body, headers=HEADERS)
    return r.json()

result = execute(
    "UPDATE orders SET status = $1 WHERE id = $2",
    ["refunded", order_id],
    reason="Customer requested refund",
    idempotency_key=f"{task_id}:{step}:{order_id}",
)

match result["status"]:
    case "committed":
        approver = (result.get("approval") or {}).get("by")
        done(approved_by=approver)          # say a human approved it, if one did
    case "rejected":  escalate(result["message"])   # a person said no
    case "expired":   retry_later()                 # nobody answered; nothing ran
    case "stale":     refresh_and_repropose()       # data moved under us
    case "denied":    give_up(result["code"])       # policy forbids it
    case "proposed":  poll(result["operation_id"])  # async: a human has it
```

```typescript TypeScript theme={null}
const GATEWAY = "http://127.0.0.1:9470";
const headers = {
  Authorization: `Bearer ${process.env.WARDEN_API_KEY}`,
  "Content-Type": "application/json",
};

async function execute(body: Record<string, unknown>) {
  const res = await fetch(`${GATEWAY}/api/v1/gateway/execute`, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
  });
  return res.json();
}

const result = await execute({
  statement: "UPDATE orders SET status = $1 WHERE id = $2",
  params: ["refunded", orderId],
  reason: "Customer requested refund",
  idempotency_key: `${taskId}:${step}:${orderId}`,
});

switch (result.status) {
  case "committed": return done(result.approval?.by);
  case "rejected":  return escalate(result.message);
  case "expired":   return retryLater();
  case "stale":     return refreshAndRepropose();
  case "denied":    return giveUp(result.code);
  case "proposed":  return poll(result.operation_id);
}
```

## Polling an async proposal

```python theme={null}
def poll(operation_id, *, wait=30):
    while True:
        r = requests.get(
            f"{GATEWAY}/api/v1/gateway/operations/{operation_id}",
            params={"wait": wait}, headers=HEADERS,
        ).json()
        if r["status"] != "proposed":
            return r
```

Retrying the original request with the same `idempotency_key` returns the same proposal, so a client that loses the ID is not stuck.

> [card] [Full API reference](https://warden.buildlab.in/api/data-plane.md)
>
> Every field of the request and the response, and what each status means.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.