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

# API SDKs

> Use the typed Python and TypeScript clients to manage Coval resources, launch runs, and read results.

The TypeScript and Python API clients below are generated from the public OpenAPI specs that power this [API reference](/api-reference/v1/introduction.md).

> **[TypeScript](https://www.npmjs.com/package/@coval/sdk)**
>
> `@coval/sdk` on npm.

> **[Python](https://pypi.org/project/coval-sdk/)**
>
> `coval-sdk` on PyPI.

> [!NOTE]
>
> Both API clients use the MIT license. Source: [coval-ai/coval-sdk](https://github.com/coval-ai/coval-sdk).

## Install

```bash TypeScript theme={null}
npm install @coval/sdk
```

```bash Python theme={null}
pip install coval-sdk
```

## Quick start

```ts TypeScript theme={null}
import { CovalClient } from '@coval/sdk';

const coval = new CovalClient({
  apiKey: process.env.COVAL_API_KEY!,
});

const page = await coval.agents.listAgents({ pageSize: 50 });
for (const agent of page.agents ?? []) {
  console.log(agent.id, agent.display_name);
}
```

```python Python theme={null}
import os
from coval_sdk import AgentsApi, ApiClient, Configuration

config = Configuration(host="https://api.coval.dev")

with ApiClient(config) as client:
    client.set_default_header("x-api-key", os.environ["COVAL_API_KEY"])
    agents = AgentsApi(client).list_agents(page_size=50)
    for a in agents.agents:
        print(a.id, a.display_name)
```

The TypeScript client groups methods under properties such as `coval.agents` and `coval.simulations`. The Python client uses one `*Api` class per resource, constructed with a shared `ApiClient`.

## Auth

Authenticate with the `x-api-key` header. The TypeScript client sets it automatically; set it on `ApiClient` in Python.

```ts TypeScript theme={null}
// Handled automatically. The CovalClient middleware sets the header for you.
const coval = new CovalClient({ apiKey: process.env.COVAL_API_KEY! });
```

```python Python theme={null}
# Set a default header so all resource clients use the key.
client.set_default_header("x-api-key", os.environ["COVAL_API_KEY"])
```

## Errors

```ts TypeScript theme={null}
import { CovalApiError, CovalNetworkError, CovalClient } from '@coval/sdk';

const coval = new CovalClient({ apiKey: process.env.COVAL_API_KEY! });

try {
  await coval.agents.getAgent({ agentId: 'ag_does_not_exist' });
} catch (err) {
  if (err instanceof CovalApiError) {
    console.error(`HTTP ${err.status} ${err.code ?? ''}: ${err.message}`);
    console.error(`  request_id: ${err.requestId ?? '-'}`);
    console.error(`  body: ${JSON.stringify(err.body)}`);
  } else if (err instanceof CovalNetworkError) {
    console.error(`Network failure after ${err.attempts} attempt(s): ${err.message}`);
  } else {
    throw err;
  }
}
```

```python Python theme={null}
from coval_sdk.exceptions import ApiException

try:
    AgentsApi(client).get_agent(agent_id="ag_does_not_exist")
except ApiException as e:
    print(f"HTTP {e.status}: {e.reason}")
    print(f"  body: {e.body}")
```

> [!NOTE]
>
> **`CovalApiError` shape**: `status`, `code`, `message`, `requestId`, `body`, `url`, `method`. The `requestId` is sourced from `x-request-id`, `x-amzn-requestid`, or the response body in that order. Include it when you file a support ticket.

### Read unvalidated Python responses

The Python client validates responses with Pydantic. If a response fails model validation, use the method's `*_without_preload_content` variant to read and parse the raw response:

```python theme={null}
import json

resp = AgentsApi(client).list_agents_without_preload_content(page_size=50)
body = json.loads(resp.data.decode("utf-8"))
for a in body["agents"]:
    print(a.get("id"), a.get("display_name"))
```

TypeScript interfaces do not validate response values at runtime.

## Retries

The TypeScript SDK retries with exponential backoff and jitter on transient failures. Defaults:

| Setting | Default | Notes |
| - | - | - |
| Max attempts | `3` | Includes the first attempt. |
| Base delay | `200ms` | Effective delay = `base * 2^(attempt-1)` plus jitter. |
| Max delay | `5000ms` | Cap on any single backoff. |
| Retryable statuses | `408, 429, 500, 502, 503, 504` | Plus network and transport errors. |
| `Retry-After` | Honored | Numeric seconds or HTTP-date both accepted. |

```ts theme={null}
// Override
const coval = new CovalClient({
  apiKey: process.env.COVAL_API_KEY!,
  retry: { maxAttempts: 5, baseDelayMs: 100, maxDelayMs: 10_000 },
});

// Disable entirely
const noRetry = new CovalClient({
  apiKey: process.env.COVAL_API_KEY!,
  retry: false,
});
```

Exhausted transport retries raise `CovalNetworkError`. Non-retryable HTTP responses raise `CovalApiError` immediately.

Python retry policy is application-controlled. Retry operations only when they are safe to repeat.

## Pagination

The Coval v1 API uses `next_page_token`-style pagination. The TypeScript SDK ships an async iterator that handles the loop for you:

```ts theme={null}
import { CovalClient, paginate, collectAll } from '@coval/sdk';

const coval = new CovalClient({ apiKey: process.env.COVAL_API_KEY! });

// Iterate lazily across pages
for await (const agent of paginate({
  fetchPage: (pageToken) => coval.agents.listAgents({ pageToken, pageSize: 50 }),
  items: (page) => page.agents,
  nextToken: (page) => page.next_page_token,
})) {
  console.log(agent.id, agent.display_name);
}

// Or buffer everything into an array
const allAgents = await collectAll({
  fetchPage: (pageToken) => coval.agents.listAgents({ pageToken, pageSize: 50 }),
  items: (page) => page.agents,
  nextToken: (page) => page.next_page_token,
});
```

`paginate` and `collectAll` work with any list endpoint. Provide `fetchPage`, `items`, and `nextToken` callbacks for the method you are calling.

> [!TIP]
>
> Pass `maxPages` to cap iteration. Useful when you want a quick preview of a large list without hitting the full backlog.

For Python, use a `while` loop on `next_page_token`.

## Customization

### Base URL

Both clients accept an API root:

```ts TypeScript theme={null}
const coval = new CovalClient({
  apiKey: process.env.COVAL_API_KEY!,
  baseUrl: 'https://api.coval.dev',
});
```

```python Python theme={null}
config = Configuration(host="https://api.coval.dev")
```

### Middleware (TypeScript)

Add request and response middleware for logging, tracing, or request IDs:

```ts theme={null}
const coval = new CovalClient({
  apiKey: process.env.COVAL_API_KEY!,
  middleware: [
    {
      async pre(ctx) {
        console.log(`-> ${ctx.init.method} ${ctx.url}`);
      },
      async post(ctx) {
        console.log(`<- ${ctx.response.status} ${ctx.url}`);
      },
    },
  ],
});
```

### Custom fetch

Swap the underlying `fetch` implementation. For example, to use `undici` with keepalive in a long-running Node process, or to stub network calls in tests:

```ts theme={null}
import { fetch as undiciFetch, Agent } from 'undici';

const dispatcher = new Agent({ keepAliveTimeout: 60_000 });
const coval = new CovalClient({
  apiKey: process.env.COVAL_API_KEY!,
  fetch: ((url, init) => undiciFetch(url, { ...init, dispatcher })) as typeof fetch,
});
```

## Versioning

Review each package's release notes before upgrading, and pin a version for reproducible builds.

## Going deeper

> **[Source repo](https://github.com/coval-ai/coval-sdk)**
>
> SDK implementations, examples, and issue tracking.

> **[OpenAPI specs](/api-reference/v1/introduction.md)**
>
> The specs that power both SDKs are published at `https://api.coval.dev/v1/openapi`.

> **[API keys](/guides/api-keys.md)**
>
> How to mint and rotate API keys from the dashboard.

> **[CLI](/cli/agents.md)**
>
> Run Coval commands from your terminal.


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