Transaction Builder

The Transaction Builder API turns a high-level intent — "supply 1,000 USDC to Aave V3" or "bridge USDC from Ethereum to Base via CCTP" — into ready-to-submit calldata for a vault's Manager contract. It's the same engine that powers the rebalance feature in the Veda Console, exposed for programmatic use.

Base URL: https://api.veda.tech

OpenAPI / Swagger: api.veda.tech/docs

Concepts

A rebalance is one or more onchain actions executed through a vault's Manager contract. The API is build-only: it returns encoded calldata and a target address; you sign and submit the transaction from your strategist address.

The workflow:

  1. Discover what actions are available for a vault — GET /actions

  2. Inspect constraints for actions with correlated parameters — GET /constraints

  3. Build a single action — POST /execute — or several atomically — POST /execute-multiple

  4. Submit the returned encoded_tx_data to the Manager from the strategist address

Every action endpoint is scoped by three path parameters:

Param
Meaning

chain

Lowercase chain slug (e.g. ethereum, base, arbitrum). See Chain Support for the full list.

vault_address

The BoringVault contract address

strategist_address

The strategist address whose merkle tree / permissions are being used. A single vault can have multiple strategists with different permitted actions.

Authentication

All Transaction Builder endpoints require an API key created in the Veda Console. Pass it as a Bearer token:

See Quick Start for how to create one. All examples below assume the key is in $VEDA_API_KEY.


1. List available actions

Returns every action the vault's merkle tree authorizes for the given strategist, along with the parameter metadata you need to build a transaction. No request body, no query parameters.

Example request

Response structure

A JSON object keyed by route (e.g. aavev3/supply). Each entry describes one action:

Field
Type
Meaning

name

string

Human-readable action name

protocol

string

Protocol identifier (e.g. AaveV3, 1Inch)

protocol_app_url

string

Link to the protocol's app, when applicable

description

string

What the action does

has_constraints

boolean

If true, params are correlated — call /constraints/{route} for valid combinations

params

array

Parameter definitions (see below)

Each params[i] is:

Field
Type
Meaning

name

string

Parameter name to pass in the execute request

type

string

Python type name (str, int, float, Decimal)

description

string

Human-readable description

required

boolean

Whether the parameter must be provided

default_value

any | null

Default if not provided (only meaningful for non-required params)

choices

array | null

Allowed values. [] means freeform; null means optional and may be omitted; a populated list means you must pick from it.

min_value

number | null

Minimum valid value, if applicable

max_value

number | null

Maximum valid value, if applicable

omitToUseAll

boolean

If true, omitting this parameter uses the vault's full balance of the token

acceptRawString

boolean

If true, the value is forwarded as-is (no numeric conversion)

Grouped choices. Most params have choices as a flat array of strings (["USDC", "USDT"]). Some params use nested arrays ([["USDC", "0xa0b8..."], ["USDT", "0xdac1..."]]) where each inner array is [display_label, value]. When building a UI, check whether the first element of choices is itself an array to decide which format you're dealing with.

Example response (abbreviated)

When has_constraints is true, the values in each param's choices are the projection of the valid combinations onto that one param. You still need to call the constraints endpoint to know which combinations are actually valid (e.g. USDC → USDT may be allowed but USDC → USDC is not).


2. Inspect parameter constraints

When has_constraints is true, not every combination of choices is valid. The constraints endpoint returns the valid combinations.

Example request

Example response

Each entry in constraints is one valid combination. Use this to drive dependent dropdowns in a UI, or to filter to a single combination in a script. Routes where has_constraints is false have fully independent parameters — any combination of values from choices is valid.

A 404 from this endpoint means the route has no parameter constraints (i.e. you didn't need to call it).


3. Build a single action

The tail matcher captures everything after the vault. It accepts either of:

  • {strategist_address}/{route} — recommended; explicit

  • {route} — the API resolves the strategist for the vault

When tail begins with a 0x…-prefixed 42-character string, that prefix is treated as the strategist address and the rest is the route. The route itself contains a slash (e.g. aavev3/supply), which is why tail:path is used.

Request body

Field
Type
Default
Description

params

object (string → any)

{}

Key-value map of action parameters, matching the /actions metadata for this route

verbose

boolean

false

Return detailed simulation output — token transfers, gas cost in ETH, and protocol-level metadata in action_api_response (including warnings). Recommended for any review step.

skip_sim

boolean

false

Skip the Tenderly simulation. Set true for faster responses or when you've already simulated.

Example request

Response structure

Field
Type
Always present?
Meaning

encoded_tx_data

string

Yes

Calldata (hex, 0x-prefixed) to submit to the vault's Manager contract

target

string

Yes

Manager contract address — the to of your transaction

description

string

Yes

Human-readable description of the action being built

action_api_response

object | null

Yes

Protocol-specific metadata. See Simulation warnings for the warning keys

simulation_status

boolean | string

When simulated

true if the Tenderly simulation succeeded; may also be an error string on failure

tenderly_simulation_url

string | null

When simulated

Link to the Tenderly simulation

simulation_logs

array

When simulated

Logs emitted during the simulation (when available)

simulation_gas_used

number | null

When simulated

Gas used during the simulation (when available)

simulation_gas_cost_eth

string | null

When verbose

Estimated gas cost denominated in ETH

token_transfers

array

When verbose

Structured list of tokens moved during the simulation (see below)

simulation_skipped

boolean

When skipped

Present and true when skip_sim: true was passed

Token transfers

When verbose: true, the response includes a token_transfers array with one entry per token movement observed during the simulation:

Field
Type
Meaning

token

string

Token symbol (e.g. USDC)

token_address

string

Token contract address

amount

string

Human-readable amount in display units

raw_amount

string

Amount in the token's smallest unit (wei / base unit)

direction

"in" | "out"

Whether the vault receives or sends the token

dollar_value

string | number | null

Estimated USD value, when a price is available

Example response

The token_transfers and simulation_gas_cost_eth fields are only present when the request includes verbose: true. Without it, you still get simulation_status, simulation_gas_used, and tenderly_simulation_url.


4. Build multiple actions (atomic batch)

Build a single atomic transaction that runs several actions in order. The response is one piece of calldata that calls the Manager with all actions packed together — recommended for any rebalance that involves more than one step (e.g. swap then supply, withdraw from one position and deposit into another).

Request body

Field
Type
Default
Description

actions

array of objects

One entry per action. Each is { "route": string, "params": object }.

verbose

boolean

false

Return detailed simulation output — token transfers, gas cost in ETH, and per-action metadata.

skip_sim

boolean

false

Skip the Tenderly simulation

An empty actions array is rejected with 400 No actions provided.

Example request

Swap 1,000 USDC into USDT via 1Inch, then supply 500 USDC into Aave V3 — in a single onchain transaction:

Response structure

Same shape as /execute, with two differences:

  • description is always "Multiple actions execution"

  • action_api_response is an array — one entry per action, in the same order as actions

Example response


Error handling

The API returns standard HTTP status codes with JSON error bodies. The error shape varies — handle both forms:

Structured error (most common for 400 / 422):

String error (some 404 and 500 responses):

FastAPI validation error (422 from Pydantic):

When parsing errors, check typeof detail — it can be a string, an object with error/details keys, or an array of validation errors. Some responses use top-level error or message keys instead of detail.

Additionally, the execute response itself may include error and details fields alongside a successful encoded_tx_data — for example, when the calldata was built but the simulation failed. Always check simulation_status even when the HTTP status is 200.

Common errors

Status
Cause

400

Missing or invalid parameters; empty actions array; unknown route in a batch

401

Missing, expired, or revoked API key

404

Unknown vault, strategist, or route (and on /constraints, a route that has no constraints)

422

Parameter validation failed (e.g. value not in choices, type mismatch)

500

Internal error — includes the offending action for batch failures

Last updated