Coval ships typed SDKs for TypeScript and Python. Both are generated from the public OpenAPI specs that power this API reference, so the surface area stays in sync with what the API accepts.
# npm has no native "install from a git subdirectory" syntax, so clone and install:git clone https://github.com/coval-ai/coval-examples.gitcd coval-examples/typescript-sdknpm installnpm run buildnpm link # or: npm pack && npm install ../coval-examples/typescript-sdk/coval-sdk-*.tgz
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);}
import osfrom coval_sdk import AgentsApi, ApiClient, Configurationconfig = 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 exposes every v1 API resource as a property on CovalClient: coval.agents, coval.conversations, coval.simulations, coval.traces, coval.metrics, and so on (22 resources total). The Python client is split into one *Api class per resource (AgentsApi, ConversationsApi, SimulationsApi, etc.) constructed against a shared ApiClient.
The Coval API gateway requires the header x-api-key in lowercase. Uppercase X-API-Key is rejected with Missing API Key.
// Handled automatically. The CovalClient middleware sets the header for you.const coval = new CovalClient({ apiKey: process.env.COVAL_API_KEY! });
# Set the header directly on the ApiClient. Do not rely on per-scheme# config.api_key["ApiKeyAuth"]; the bundled spec splits the security scheme# per tag (Coval_Agents_API_ApiKeyAuth, Coval_Conversations_API_ApiKeyAuth,# etc.), so setting a default header is the pattern that works# across all 22 resources.client.set_default_header("x-api-key", os.environ["COVAL_API_KEY"])
If you see {"message": "Missing API Key"} from the gateway, check that the header name is lowercase. The TypeScript SDK takes care of this for you; the Python SDK leaves it to your set_default_header call.
from coval_sdk.exceptions import ApiExceptiontry: 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}")
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.
The Python client uses strict pydantic v2 models for every response, including regex patterns on IDs (e.g., agent_id must match ^[A-Za-z0-9]{22}$). If your org has historical data that predates the current spec, for example an agent created when IDs had a different shape, pydantic will raise a ValidationError mid-stream and you will lose the rest of the page.The fix is to call the *_without_preload_content variant of any method and parse the response yourself:
import jsonresp = 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"))
Every generated method has a _without_preload_content sibling. The TypeScript SDK does not have this issue: its types are emitted as interface declarations with no runtime validation, so unknown fields pass through.
When all attempts are exhausted on a transport error, the client throws CovalNetworkError. When a non-retryable status (e.g., 400, 404) comes back, it falls through to the normal error path and raises CovalApiError immediately.For Python, wrap your own calls with tenacity or a similar library.