Skip to content
Hightop docs header art
Hightop
API and Integrations

TypeScript SDK#

@hightop/sdk is the official TypeScript client for the Agent API. It ships the generated Agent API types and endpoint metadata plus a small hand-written client that handles auth, the fetch transport, idempotency enforcement, errors, timeouts, raw requests, and operation polling.

Reach for the SDK when you build agents or services in TypeScript or JavaScript and want types, autocompletion, and the lifecycle helpers handled for you. For the full method-by-method listing, see the SDK Reference. To compare against the CLI, MCP, and raw HTTP, see Choose Your Surface.

Install#

terminal
command
npm install @hightop/sdk

The SDK targets Node 20 or newer and is published to the public npm registry.

Configure a client#

Create one HightopAgentClient and reuse it. Configure exactly one auth mode — header-key or bearer token. See Authentication for how to choose.

Header-key auth:

typescript
example
import { HightopAgentClient } from '@hightop/sdk'
 
const client = new HightopAgentClient({
  baseUrl: process.env.HIGHTOP_BASE_URL,
  agentId: process.env.HIGHTOP_AGENT_ID,
  apiKey: process.env.HIGHTOP_API_KEY,
})

Bearer-token auth (for OAuth-issued tokens):

typescript
example
const client = new HightopAgentClient({
  baseUrl: process.env.HIGHTOP_BASE_URL,
  bearerToken: process.env.HIGHTOP_BEARER_TOKEN,
})

baseUrl defaults to https://api.hightop.com. timeoutMs defaults to 30000. You may pass a custom fetch implementation. Auth can be omitted to call public routes, but protected endpoint calls throw until agentId/apiKey or bearerToken is set.

Quickstart#

Read the authenticated agent, then run a write through to a terminal state:

typescript
example
import { HightopAgentClient, createIdempotencyKey } from '@hightop/sdk'
 
const client = new HightopAgentClient({
  baseUrl: process.env.HIGHTOP_BASE_URL,
  agentId: process.env.HIGHTOP_AGENT_ID,
  apiKey: process.env.HIGHTOP_API_KEY,
})
 
// Read
const self = await client.self.get()
console.log(self.agent.wallet_address)
 
// Write — supply an idempotency key for every mutation
const repay = await client.borrow.repay(
  { asset: 'GREEN', amount_usd: '10' },
  { idempotencyKey: createIdempotencyKey() },
)
 
// Poll the returned operation until it settles
const final = await client.operations.wait(repay.operation_id)
console.log(final.operation.status)

Amounts are decimal strings, never numbers. Bare amount fields are asset-unit amounts ("1" = 1 USDC); fields named amount_usd (like the repay above) are USD-denominated. See Conventions.

Typed domain helpers#

The most common workflows are exposed as domain methods, for example:

typescript
example
const balances = await client.balances.list({ limit: 50 })
const usage = await client.self.usage()
const quote = await client.conversions.quote(
  { from_asset: 'USDC', to_asset: 'ETH', amount: '1', slippage_percent: 1 },
  { idempotencyKey: createIdempotencyKey() },
)

The OpenAPI document is public and needs no credentials. Capabilities require auth (agent:read):

typescript
example
// Public — no credentials needed:
const openapi = await new HightopAgentClient({ baseUrl: 'https://api.hightop.com' }).openapi.get()
 
// Requires auth (agent:read):
const capabilities = await client.capabilities.json()

The full set of helpers is listed in the SDK Reference.

Every endpoint: the typed request map#

Domain helpers cover the common paths; client.request() covers every catalogued /v1/agent/* endpoint with full type inference on the request and response:

typescript
example
const oneOff = await client.request(
  'POST /v1/agent/one-off-payments',
  { to: '0x...', asset: 'USDC', amount_usd: '25' },
  { idempotencyKey: createIdempotencyKey() },
)

The generated artifact exports the supporting types:

typescript
example
import type {
  AgentApiRequestFor,
  AgentApiResponseFor,
  AgentApiEndpointKey,
} from '@hightop/sdk'

These are regenerated from the Agent API contract, so they always match the live surface.

Idempotency#

Every mutating endpoint requires an idempotency key. Generate one per logical operation with createIdempotencyKey(prefix?), and reuse the same key only when retrying the same logical request.

typescript
example
const key = createIdempotencyKey('payout')
await client.request('POST /v1/agent/one-off-payments', body, { idempotencyKey: key })
// Safe to retry with the same key + same body if the network result is unknown

Reusing a key with a different body returns idempotency_key_reuse_mismatch. Completed responses are stored for 24h and a retry replays the original with X-Idempotency-Replayed: true — see Conventions for the replay contract and Going to Production for retry strategy.

Operation polling#

Operation-backed (money-movement) writes return an operation id. client.operations.wait() polls until the operation reaches a terminal status or the wait times out:

typescript
example
try {
  const result = await client.operations.wait(repay.operation_id, { timeoutMs: 60_000 })
} catch (error) {
  if (error instanceof HightopAgentOperationWaitTimeoutError) {
    // Still pending — the operation may yet settle; re-poll later by id
    console.log(error.operation?.status)
  }
}

See Operations and Lifecycle for terminal statuses.

Raw requests#

rawRequest is an escape hatch for support workflows. It allows only known /v1/agent/* routes plus the OpenAPI and capabilities routes, and requires an explicit idempotencyKey for routes that need one:

typescript
example
const operation = await client.rawRequest({
  method: 'GET',
  path: '/v1/agent/operations/operation-id',
  query: { include: 'onchain' },
})

Errors and timeouts#

Non-2xx responses throw HightopAgentSDKError, which preserves the HTTP status, the normalized Agent API error, the original response body, response headers, and request id:

typescript
example
import { HightopAgentClient, HightopAgentSDKError, createIdempotencyKey } from '@hightop/sdk'
 
try {
  await client.borrow.repay({ asset: 'GREEN', amount_usd: '10' }, { idempotencyKey: createIdempotencyKey() })
} catch (error) {
  if (error instanceof HightopAgentSDKError && error.code === 'asset_not_allowed') {
    console.log(error.agentError?.details)
  }
}

Helpers for narrowing errors without instance checks:

typescript
example
import { getAgentApiError, getAgentApiErrorByCode, isAgentErrorCode } from '@hightop/sdk'
 
const agentError = getAgentApiError(error)
if (agentError && isAgentErrorCode(agentError, 'quote_expired')) {
  console.log(agentError.details.quote_id)
}
 
const rateLimit = getAgentApiErrorByCode(error, 'rate_limited')
if (rateLimit) {
  console.log(rateLimit.details.limit_count)
}

Request timeouts are synthesized client-side with code request_timeout. A timeout means the response was not received in time; if the request never reached the server it is not idempotency-cached. See Errors for the full code list.

Next#

Previous

Developer Tools

Next

SDK Reference