> For the complete documentation index, see [llms.txt](https://docs.veda.tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.veda.tech/api/api-reference.md).

# API Reference

The full Veda Console API surface is described by an OpenAPI 3 specification. The interactive Swagger UI is the source of truth for request and response schemas, parameter shapes, and the list of supported endpoints.

## OpenAPI / Swagger

{% hint style="info" %}
[**Open the interactive Swagger docs →**](https://api.veda.tech/docs)
{% endhint %}

* **Swagger UI:** [api.veda.tech/docs](https://api.veda.tech/docs)
* **OpenAPI JSON:** [api.veda.tech/openapi.json](https://api.veda.tech/openapi.json)
* **Version:** `1.0.0`

You can use the OpenAPI spec directly to generate clients in your language of choice (`openapi-generator`, `oapi-codegen`, `openapi-typescript`, etc.), drive contract tests, or import into Postman / Insomnia.

## Base URL

```
https://api.veda.tech
```

## Authentication

All endpoints are authenticated with an API key passed as a Bearer token:

```
Authorization: Bearer veda_user_live_...
```

API keys are created in the [Veda Console](https://console.veda.tech) — see [Quick Start](/api/quick-start.md).

## Rate limits & timeouts

* **Rate limit:** 60 requests per minute, per API key. When you exceed the limit, the API returns `429 Too Many Requests` — back off with exponential delay and retry.
* **Request timeout:** 30 seconds for most endpoints. Build endpoints (`/execute`, `/execute-multiple`) with simulation enabled can take significantly longer. Pass `skip_sim: true` when you don't need a Tenderly simulation — it's the most common way to get faster responses.

If you need a higher limit for a production workload, reach out to your Veda contact with the expected request volume.

## Conventions

* **JSON only.** All requests and responses are `application/json` unless noted otherwise.
* **Envelopes.** Newer endpoints ([Vaults](/api/vaults.md), [Policy Manager & Merkle Trees](/api/policy-manager-and-merkle-trees.md)) wrap responses: `{ "data": { ... } }` for a single resource, `{ "data": [ ... ], "page": { ... } }` for a collection. [Transaction Builder](/api/transaction-builder.md) endpoints predate this and return their payload at the top level.
* **JSON keys** are `snake_case`. Timestamps are ISO-8601 in UTC. Paths have no trailing slashes.
* **Chain slugs** are lowercase (`ethereum`, `base`, `arbitrum`, etc.). See [Chain Support](/resources/chain-support.md) for the full list.
* **Addresses** are EIP-55 checksummed in responses; lowercase or checksummed is accepted on request.
* **Amounts** in request bodies are in the token's display units (e.g. `1000` means 1,000 USDC, not 1,000 wei).
* **Errors** use one of two envelopes — see [Errors](#errors) below.

## Errors

Non-2xx responses from application endpoints ([Vaults](/api/vaults.md), [Policy Manager & Merkle Trees](/api/policy-manager-and-merkle-trees.md)) use a single envelope:

```json
{
  "error": {
    "code":    "snake_case_code",
    "message": "Human-readable description.",
    "details": {}
  }
}
```

`details` is an object whose contents depend on the code — `rate_limited` includes a `retry_after` value in seconds, and so on. Today `details` is most often an empty object.

**Standard codes:**

| HTTP  | Code                                        |
| ----- | ------------------------------------------- |
| `400` | `invalid_root_hash`                         |
| `404` | `vault_not_found`, `tree_not_found`         |
| `429` | `rate_limited` (with `details.retry_after`) |
| `500` | `internal_error`                            |

{% hint style="info" %}
**Tenant denial returns 404, never 403.** For tenant-scoped resources (vaults, trees), the API does not distinguish "doesn't exist" from "exists but not in your tenant" — callers cannot probe for the existence of other tenants' resources.
{% endhint %}

### Authentication errors

Authentication is enforced at the gateway, ahead of the application, so 401 / 403 responses **do not use the standardized envelope** above. They return a flat `message` field instead:

```json
{ "message": "Unauthorized" }
```

* `401 { "message": "Unauthorized" }` — no `Authorization` header.
* `403 { "message": "Forbidden" }` — header is present but the bearer is invalid, expired, or revoked.

Treat both as "re-authenticate." Once the request reaches the application, all other failures use the envelope above.

## Versioning

The Veda API uses **major versions in the URL path**. Every endpoint sits under a `/v{N}/` prefix. The current major version is `v1`.

### Deprecations

Endpoints or fields slated for removal in a future major version are marked as deprecated in the OpenAPI spec and announced in the [Change Log](/api/change-log.md) with at least **30 days' notice**. During the deprecation window, calls succeed and the response includes a `Deprecation` header pointing to the replacement.

### Pinning a version

Always pin the version explicitly in your client (`/v1/...`). Don't rely on host-level redirects from an unversioned path — they're not guaranteed and may change.
