Skip to main content
The Vetta REST API is the programmatic interface to the hosted managed agent. Everything the CLI and the TypeScript SDK do is built on the endpoints documented here.

Base URL

All requests go to a single, versioned base URL. Every path in this reference is relative to it.

Versioning

The API carries two version coordinates, designed in from day one:
  • A path version (/v1) that changes only for a wholesale redesign. There is no reflexive /v2 — breaking changes are managed by the date version below, not the path.
  • A date version sent per request in the Vetta-Version header (format YYYY-MM-DD), which pins the exact wire contract your integration was built against.
Omitting the header pins your organization to the version in effect when its first key was created. Additive changes (new fields, new endpoints) are made in place within a date version; treat unknown response fields as forward-compatible and ignore them.

Deprecation policy

Backwards-incompatible changes only ever ship behind a new date version — never silently. When a field or behavior is deprecated we publish it in the changelog, keep the old behavior available for a minimum 6-month sunset window, Pin Vetta-Version in production so a new default version can never break you.
There is no deprecation response header today. Deprecations are announced in the changelog only; do not write a client that keys off a header the API does not send.

Authentication

Authenticate with an organization-scoped API key in the Authorization header using the Bearer scheme.
Keys belong to an organization and inherit its resources and credit balance. See Authentication for creating, scoping, and rotating keys.

Request & response conventions

  • Request and response bodies are JSON. Send Content-Type: application/json on any request with a body.
  • Timestamps are RFC 3339 strings in UTC (e.g. 2026-08-20T17:00:00Z), suffixed _at. Fields that need client-side arithmetic are also exposed as epoch millis, suffixed _at_ms.
  • Object ids are prefixed by type — one prefix per type (e.g. agt_ agents, ses_ sessions, cmp_ computers, key_ keys, led_ ledger entries). The random suffix is Crockford base32.
  • Money is always an integer count of micro-USD in fields suffixed _micro_usd (1 USD = 1,000,000 micro-USD). Never floating-point dollars on the wire — clients convert for display only. See Credits.
  • The single latency/price knob is the completion window: immediate | priority | loose. These exact strings travel on the wire everywhere; the default is immediate.

Request ids

Every response — success or error — carries an x-request-id header. Log it; quoting it in a support request lets us trace the exact call. On errors the same value is mirrored inside the error envelope as error.request_id.

Idempotency

Every mutating POST accepts an Idempotency-Key header (also honored on the RPC-style verbs like top-ups, session messages, and computer creation). Reusing the same key replays the original response instead of performing the operation twice, making retries safe.
The contract:
  • Same key, same body → the original response is replayed. A replay carries an Idempotency-Replayed: true response header so you can tell a fresh result from a cached one.
  • Same key, different body409 (validation_failed). A key binds to the exact request that first used it; reusing it with a changed payload is rejected rather than silently ignored.
  • Concurrent requests with the same key → the first wins and the rest return 409 while it is in flight; retry after it settles to receive the replayed result.
Keys are scoped to your organization and retained for 24 hours. Use a fresh UUID per logical operation. Purely idempotent verbs (GET) ignore the header.

Pagination

List endpoints are cursor-paginated with limit and after, returning { data, has_more, next_cursor }. The session events log is a separate, oldest-first seq-cursor contract. See Pagination.

Machine-readable description

GET /v1/openapi.json returns an OpenAPI 3.1 description of this API, generated from the server’s own route table — so it lists exactly the routes the deploy you are talking to serves, no more and no less. It needs no API key. Each operation carries the scope a caller must hold as x-vetta-scope, and the shared error envelope as its default response. Request and response bodies are not described yet; use the resource pages below for those.

Errors

Errors use the single typed JSON envelope with standard HTTP status codes, and always include a request_id. See Errors.

Rate limits & concurrency

Two independent limits apply per organization:
  • Request rate: 6000 requests/minute per organization across the control plane (list, read, and mutate calls), and 3000 requests/minute per API key, so one key cannot spend the whole organization’s budget. Fixed 60-second window.
  • Session concurrency: 50 sessions in the running state at once. Starting a session beyond the cap queues it in queued until a slot frees.
When you exceed the request rate the API returns 429 with a rate_limited error and a Retry-After header (seconds to wait). Back off and retry after that delay. Rate-limit state is also returned in response headers: RateLimit-* describes whichever of the two limits is closest to binding. The API also answers 429 with rate_limited and a Retry-After when the platform itself is momentarily at capacity — it never answers a capacity problem with a 500, so a 429 is always safe to back off on and retry.
Concurrency limits are raised on request. The request-rate and concurrency numbers above are the default org tier; your organization’s effective limits are reflected in the RateLimit-* headers.

Resources

Every page above is one row of the same route table the TypeScript SDK and the CLI are generated against, so an operation you find here has a method and a command with the same name.

TypeScript SDK

npm i @usenaive-sdk/vetta — one typed method per route, with the full method index.

CLI

npm i -g @usenaive-sdk/vetta-cli — the same surface from a terminal or CI.