---
title: "Parameter effects and outputs"
description: "What each request parameter changes and what comes back — the side effects and response fields for the account, wallet, and signing endpoints, and how signing stands in for transactions."
---

> Documentation Index
> Fetch the complete documentation index at: https://tee.hypetrade.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Parameter effects and outputs

The API reference lists each endpoint's request and response shapes. This page
reads the other direction: for the account, wallet, and signing endpoints, what
does changing a given parameter actually *do* (its effect and side effects), and
what appears in the response (its output). Every row reflects current behavior;
see the linked API pages for the full schemas.

Two conventions used below:

- **Effect** — what the parameter changes, including error paths and custody or
  quota side effects.
- **Output** — the response field(s) the parameter drives. A parameter with no
  output row is never echoed.

## Creating an account

`POST /v1/accounts` — see [Accounts](/api/accounts/). Creating an account always
derives its **first wallet**, charged to the tenant's `maxWallets` allowance
*before* any key material is generated — so a create with no wallet headroom
left returns `409 quota_wallets_exceeded` and nothing is created.

| Parameter | Effect | Output |
|---|---|---|
| `displayName` | Normalized (NFKD) to 3–64 characters and must keep at least one Latin letter; the account **slug is derived from it**. A name that cannot normalize returns `400 invalid_parameter`. | `account.slug` (server-generated), `account.displayName` |
| `kind` | `HD` makes a mnemonic account you can `derive` more wallets from; `PK` is a single imported key, where `derive` is refused `422 unsupported_for_kind` and `import` is used instead. A `PK` create without `secret` is `400 invalid_body`. | `account.kind` |
| `secret` | On `HD`, omit it to have the service generate a mnemonic; on `PK` it is the private key and is required. The secret itself is never returned — it leaves only through the sealed [export path](/api/export/). | drives `generatedSecret` (`true` when omitted, i.e. generated) |
| `defaultNetwork` | Fixes the chain each derived address signs on, and therefore the default `chainId` for typed-data signing. A well-formed slug for a network the workspace lacks is `400 unsupported_network`. Not changeable after creation. | `account.defaultNetwork`; every `address.network` / `address.chainId` |
| `hasOwnPassword` | The Cold Vault tier: the account gets a password separate from the session and is **locked immediately after creation** (no custody window), so it must be unlocked before first use. Requires `accountPassword`. Omitted or `false` creates the account unlocked with a custody window. | `account.hasOwnPassword`; a Cold Vault create returns `account.locked: true` |
| `accountPassword` | The Cold Vault password, held to the same policy as a workspace password (under 12 characters is `422 weak_password`). Required when `hasOwnPassword` is set and rejected without it (`400 invalid_body`). Used once, never stored. | — |

## Unlocking and locking an account

`POST /v1/accounts/{slug}/unlock` and `.../lock` — see
[Workspace token routes](/api/workspace/). Both return `204` with no body and
are scope-free (any workspace token).

| Parameter | Effect | Output |
|---|---|---|
| `accountPassword` (unlock) | Opens the account and starts a fixed custody window (`accountAbsoluteSec`). Re-verifying an account that is **already** live does not renew its deadline. The workspace idle clock slides on admission **even when the password then turns out wrong**. Shares the tenant mint/KDF budget, so it can return `429 mint_rate_limited`. A wrong password is `401 bad_password` with a per-account backoff (1/2/4/8s → `429 account_unlock_rate_limited`); the fifth consecutive failure — or the mint-budget limit, whichever is lower — retires the whole session, after which calls return `401 session_expired`. | `204` |
| (lock, no body) | Locks the account immediately and zeroizes its in-memory key material. A manual lock is not auto-reopened even while a durable scoped key pins the session. | `204` |

## Wallet endpoints

See [Accounts](/api/accounts/). Every wallet-producing call reserves the
tenant's cross-workspace `maxWallets` headroom *before* the core call, so a call
over the ceiling is `409 quota_wallets_exceeded` and derives nothing.

| Endpoint / parameter | Effect | Output |
|---|---|---|
| `POST .../wallets` — `count` (1–500) | Derives `count` wallets on an `HD` account (`PK` is `422 unsupported_for_kind`). | `before` and `after` — the account's **total** wallet count on each side, not the number added |
| `POST .../wallets/allocate` (no body) | Hands out the next unallocated wallet of an `HD` account: in buffer mode a pre-derived one, refilling asynchronously; otherwise derived on demand. Marks the wallet with an internal reserved tag. | the allocated `wallet` |
| `POST .../wallets/seed-allocated` — `count` (0–100,000) | Migration prep: marks the lowest `count` wallet ids as already allocated so `allocate` skips them. Idempotent; a `count` above the account's wallet total is `400`. | `allocated`, `total` |
| `POST .../wallets/import` — `privateKey`, `vm?` | Imports one wallet into a `PK` account (`HD` is `422 unsupported_for_kind`); an unparseable key is `400 invalid_private_key`. `vm` (`evm` or `svm`) pins the scheme for an ambiguous key form, otherwise it is inferred. A `PK` wallet carries an address on both chains. | the imported `wallet` |
| `PUT .../wallets/{id}/tags` — `tags` (max 32) | **Replaces** the whole caller-visible tag list rather than merging; each tag is trimmed, Unicode-normalized, and de-duplicated. Reserved `sys:*` tags are stripped from the input and preserved from the existing set. | the `wallet` with its public tags |

## Signing (and how it stands in for transactions)

`POST /v1/sign/*` — see [Sign](/api/sign/). tee-docker signs; it never builds,
simulates, submits, or broadcasts, and there are no `/transactions` or balance
routes. **The transaction-signing surface is `/sign/digest` (EVM) and
`/sign/bytes` (Solana):** you build and hash the transaction yourself, have the
service sign, then assemble the signed transaction and broadcast it from your
own client.

Across all four routes, `address` (1–128 chars) is resolved by public key across
the whole workspace, and its owning account is unlocked lazily — so a locked
Cold Vault owner returns `423 account_locked` and an unknown or other-tenant
address returns `404 account_not_found`. Every route requires the `sign` scope
and is **workspace-token-only**: a scoped API key is refused `403 scope_denied`
regardless of tier. Every response echoes the resolved `address`.

| Endpoint / parameter | Effect | Output |
|---|---|---|
| `/sign/message` — `message`, `encoding?` | `encoding` is `personal_sign`, `raw`, or `ed25519`. With an encoding the service uses the encoded path and the response gains a `messageHash`; without one it uses the address's default scheme and returns no `messageHash`. An encoding the address's VM cannot perform is `501 unsupported_operation`. | `signature`, and `messageHash` only when an `encoding` was given |
| `/sign/typed-data` — `typedData`, `chainId?` | **EVM only** (`422 unsupported_for_kind` otherwise). The envelope must carry `domain`, `types`, `primaryType`, and `message`, and `primaryType` must name a struct in `types`. `chainId` **defaults to the address's own network** — there is no silent mainnet default. If the payload's `domain.chainId` is readable and disagrees with the signing chain, the request is `400 chain_id_mismatch` naming both. The caller's exact object is signed; validation never rewrites the signed bytes. | `signature`, `domainSeparator`, `structHash` |
| `/sign/digest` — `digest` | **EVM (secp256k1) only.** `digest` must be a lowercase `0x`-hex 32-byte value and is signed **verbatim** — no keccak, no EIP-191 prefix. Build the transaction `v` from `recovery` (the yParity: use it directly for typed transactions, or `35 + 2·chainId + recovery` for legacy EIP-155). | `r`, `s`, `recovery`, `signature` |
| `/sign/bytes` — `message`, `encoding?` | **Solana (ed25519) only.** `message` is `hex` (default, lowercase `0x`) or `base64` per `encoding`, decoded with a strict round-trip, and must be 1 byte to 16 KiB. The exact bytes are signed verbatim — you compile the Solana message, the service signs, and you attach the signature. | `signature` (base58) and `signatureHex` |

> **Why there is no transaction endpoint**
>
> An earlier design relayed chain RPC and offered build/simulate/send routes. The
> service now custodies keys and signs only: it holds no RPC endpoint and returns
> a signature, never a broadcast result. Keeping the RPC endpoint and broadcast on
> your side is deliberate — the signing token is a bearer instrument, and the
> chain a payload lands on is the caller's to choose and hold.

Source: https://tee.hypetrade.xyz/concepts/parameter-effects/index.mdx
