Skip to content
Hightop docs header art
Hightop
Developer Tools

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. The full method-by-method SDK reference is included on this page. 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.

Common workflows are exposed as typed domain methods (client.balances.list(), client.self.usage(), client.conversions.quote(), …); the full set is enumerated in the SDK reference below.

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.

TypeScript SDK Reference#

This page is generated from the Agent API endpoint catalog and the public @hightop/sdk client surface. Current package version: @hightop/sdk@0.1.9.

Client Construction#

The SDK exports HightopAgentClient, createIdempotencyKey, HightopAgentSDKError, HightopAgentOperationWaitTimeoutError, generated endpoint metadata, and generated request/response types.

Config fieldPurpose
baseUrlAgent API origin. Defaults to https://api.hightop.com.
agentId + apiKeyHeader-key auth. Configure both together.
bearerTokenOAuth bearer token auth. Do not combine with header-key auth.
fetchOptional fetch implementation for tests or custom runtimes.
timeoutMsDefault request timeout in milliseconds.

Domain Helpers#

Endpoint paths are relative to /v1/agent

HelperEndpointIdempotencySignatureDescription
client.self.get(options?)GET/selfnot required() => Promise<AgentApiSelfResponse>Return the authenticated agent and wallet context.
client.self.usage(options?)GET/self/usagenot required() => Promise<AgentApiSelfUsageResponse>Return current Agent API rate-limit and usage state.
client.self.limits(options?)GET/self/limitsnot required() => Promise<AgentApiSelfLimitsResponse>Return effective operation permissions, spend/swap limits, and current-period usage.
client.capabilities.get(options?)GET/capabilitiesnot required() => Promise<AgentApiCapabilitiesResponse>Return authenticated runtime capabilities.
client.capabilities.json(options?)GET/capabilities.jsonnot required() => Promise<AgentApiCapabilitiesResponse>Return Agent API capabilities as JSON.
client.openapi.get(options?)GET/openapi.jsonnot required() => Promise<Record<string, unknown>>Fetch the public Agent API OpenAPI document.
client.account.get(options?)GET/accountnot required() => Promise<AgentApiAccountResponse>Return a scoped account summary.
client.balances.list(query?, options?)GET/balancesnot required(query?: Record<string, unknown>) => Promise<AgentApiBalancesResponse>List balances for the authenticated agent wallet.
client.balances.cash(query?, options?)GET/balances/cashnot required(query?: Record<string, unknown>) => Promise<AgentApiBalancesResponse>List cash balances.
client.operations.list(query?, options?)GET/operationsnot required(query?: AgentApiOperationsQuery) => Promise<AgentApiOperationsResponse>List AgentOperation rows.
client.operations.get(id, query?, options?)GET/operations/{id}not required(id: string, query?: Omit<AgentApiOperationDetailQuery, "id">) => Promise<AgentApiOperationResponse>Fetch one operation, optionally including onchain details.
client.operations.wait(id, options?)GET/operations/{id}not required(id: string, options?: WaitForOperationOptions) => Promise<AgentApiOperationResponse>Poll an operation until a terminal status or timeout.
client.borrow.get(options?)GET/borrownot required() => Promise<AgentApiBorrowResponse>Return borrow summary.
client.borrow.repay(body, options)POST/borrow/repayrequired via options.idempotencyKey(body: AgentApiBorrowRepayRequest, options: HightopAgentRequestOptions) => Promise<AgentApiWriteResponse>Create a debt repayment operation.
client.borrow.deleverage(body, options)POST/borrow/deleveragerequired via options.idempotencyKey(body: AgentApiDeleverageRequest, options: HightopAgentRequestOptions) => Promise<AgentApiWriteResponse>Create a target-LTV deleverage operation.
client.conversions.quote(body, options)POST/conversions/quoterequired via options.idempotencyKey(body: AgentApiConversionQuoteRequest, options: HightopAgentRequestOptions) => Promise<AgentApiConversionQuoteResponse>Create a stateful conversion quote.
client.conversions.execute(body, options)POST/conversionsrequired via options.idempotencyKey(body: AgentApiConversionExecuteRequest, options: HightopAgentRequestOptions) => Promise<AgentApiWriteResponse>Execute a conversion from a quote.
client.simulate.request(body, options?)POST/simulatenot required(body: AgentApiSimulateRequest) => Promise<AgentApiSimulateResponse>Validate a write without broadcasting; policy checks run where applicable at policy depth.
client.x402.sign(body, options)POST/x402/signrequired via options.idempotencyKey(body: AgentApiX402SignRequest, options: HightopAgentRequestOptions) => Promise<AgentApiX402SignResponse>Sign a Base USDC x402 payment authorization.
client.x402.quote(body, options?)POST/x402/quotenot required(body: AgentApiX402QuoteRequest) => Promise<AgentApiX402QuoteResponse>Fetch a URL and return its supported x402 price without paying.
client.x402.purchase(body, options)POST/x402/purchaserequired via options.idempotencyKey(body: AgentApiX402PurchaseRequest, options: HightopAgentRequestOptions) => Promise<AgentApiX402PurchaseResponse>Fetch a URL, satisfy an x402 challenge, and return the upstream response.
client.request(key, payload?, options?)multipledepends on endpoint<Key extends AgentApiEndpointKey>(key: Key, payload?: AgentApiRequestFor<Key>) => Promise<AgentApiResponseFor<Key>>Typed generic access to every catalogued Agent API endpoint.
client.rawRequest(request)multipledepends on endpoint<Response = unknown>(request: HightopAgentRawRequest) => Promise<Response>Support/debug path for known /v1/agent routes plus public OpenAPI.

Generic Endpoint Map#

client.request(key, payload, options) covers every catalogued endpoint below. For mutating endpoints marked required, pass options.idempotencyKey; createIdempotencyKey() generates a suitable value.

Endpoint keyRequest typeResponse typePath paramsQuery paramsBody paramsIdempotencyRate class
GET /v1/agent/selfundefinedAgentApiSelfResponsenonenonenonenot requiredread
GET /v1/agent/self/usageundefinedAgentApiSelfUsageResponsenonenonenonenot requiredread
GET /v1/agent/self/limitsundefinedAgentApiSelfLimitsResponsenonenonenonenot requiredread
GET /v1/agent/capabilitiesundefinedAgentApiCapabilitiesResponsenonenonenonenot requiredread
GET /v1/agent/capabilities.jsonundefinedAgentApiCapabilitiesResponsenonenonenonenot requiredread
GET /v1/agent/accountundefinedAgentApiAccountResponsenonenonenonenot requiredread
GET /v1/agent/assetsAgentApiResourceListQueryAgentApiAssetsResponsenonecursor, limitnonenot requiredread
GET /v1/agent/protocolsAgentApiResourceListQueryAgentApiProtocolsResponsenonecursor, limitnonenot requiredread
GET /v1/agent/balancesAgentApiResourceListQueryAgentApiBalancesResponsenonecursor, limitnonenot requiredread
GET /v1/agent/balances/cashAgentApiResourceListQueryAgentApiBalancesResponsenonecursor, limitnonenot requiredread
GET /v1/agent/activityAgentApiActivityQueryAgentApiActivityResponsenonecursor, limit, type, sincenonenot requiredread
GET /v1/agent/operationsAgentApiOperationsQueryAgentApiOperationsResponsenonecursor, limit, status, type, sincenonenot requiredread
GET /v1/agent/operations/{id}AgentApiOperationDetailQueryAgentApiOperationResponseidincludenonenot requiredread
GET /v1/agent/recipientsAgentApiRecipientsQueryAgentApiRecipientsResponsenonecursor, limitnonenot requiredread
GET /v1/agent/recipients/{id}AgentApiRecipientDetailQueryAgentApiRecipientResponseidnonenonenot requiredread
POST /v1/agent/recipients/resolveAgentApiRecipientResolveRequestAgentApiRecipientResponsenonenoneto, asset, actionnot requiredread
POST /v1/agent/paymentsAgentApiPaymentCreateRequestAgentApiWriteResponsenonenoneto, asset, deliver_as, note, slippage_percent, prefer, amount, amount_usdrequiredwrite
GET /v1/agent/paymentsAgentApiResourceListQueryAgentApiOperationsResponsenonecursor, limitnonenot requiredread
GET /v1/agent/payments/{id}AgentApiResourceDetailQueryAgentApiOperationResponseidincludenonenot requiredread
POST /v1/agent/one-off-paymentsAgentApiOneOffPaymentCreateRequestAgentApiWriteResponsenonenoneto, asset, note, unlock_delay_seconds, expires_in_seconds, amount, amount_usdrequiredwrite
GET /v1/agent/one-off-paymentsAgentApiResourceListQueryAgentApiOperationsResponsenonecursor, limitnonenot requiredread
GET /v1/agent/one-off-payments/{id}AgentApiResourceDetailQueryAgentApiOperationResponseidincludenonenot requiredread
POST /v1/agent/withdrawals/to-bankAgentApiWithdrawalToBankRequestAgentApiWriteResponsenonenonemethod_id, asset, note, amount, amount_usdrequiredwrite
POST /v1/agent/withdrawals/to-cryptoAgentApiWithdrawalToCryptoRequestAgentApiWriteResponsenonenonedestination_id, asset, note, amount, amount_usdrequiredwrite
GET /v1/agent/withdrawalsAgentApiResourceListQueryAgentApiOperationsResponsenonecursor, limitnonenot requiredread
GET /v1/agent/withdrawals/{id}AgentApiResourceDetailQueryAgentApiOperationResponseidincludenonenot requiredread
GET /v1/agent/withdrawal-methodsAgentApiResourceListQueryAgentApiWithdrawalMethodsResponsenonecursor, limitnonenot requiredread
GET /v1/agent/deposit-methodsAgentApiResourceListQueryAgentApiDepositMethodsResponsenonecursor, limitnonenot requiredread
GET /v1/agent/deposit-addressAgentApiDepositAddressQueryAgentApiDepositAddressResponsenoneasset, chainnonenot requiredread
GET /v1/agent/earnAgentApiResourceListQueryAgentApiEarnResponsenonecursor, limitnonenot requiredread
GET /v1/agent/earn/{id}AgentApiEarnDetailQueryAgentApiEarnPositionResponseidnonenonenot requiredread
GET /v1/agent/earn/opportunitiesAgentApiResourceListQueryAgentApiEarnOpportunitiesResponsenonecursor, limitnonenot requiredread
POST /v1/agent/earn/depositAgentApiEarnDepositRequestAgentApiWriteResponsenonenoneasset, vault_id, use_best_available, amount, amount_usdrequiredwrite
POST /v1/agent/earn/withdrawAgentApiEarnWithdrawRequestAgentApiWriteResponsenonenoneposition_id, withdraw_all, destination_asset, allow_conversion, amount, amount_usdrequiredwrite
POST /v1/agent/earn/moveAgentApiEarnMoveRequestAgentApiWriteResponsenonenonefrom_position_id, move_all, to_vault_id, to_best_available, amount, amount_usdrequiredwrite
POST /v1/agent/earn/rewards/claimAgentApiEarnRewardsClaimRequestAgentApiWriteResponsenonenoneprotocolsrequiredwrite
GET /v1/agent/borrowundefinedAgentApiBorrowResponsenonenonenonenot requiredread
POST /v1/agent/borrowAgentApiBorrowRequestAgentApiWriteResponsenonenoneasset, max_ltv_after, amount, amount_usdrequiredwrite
GET /v1/agent/borrow/collateralAgentApiResourceListQueryAgentApiCollateralResponsenonecursor, limitnonenot requiredread
GET /v1/agent/borrow/collateral-optionsAgentApiResourceListQueryAgentApiCollateralOptionsResponsenonecursor, limitnonenot requiredread
POST /v1/agent/borrow/repayAgentApiBorrowRepayRequestAgentApiWriteResponsenonenoneasset, repay_all, source_asset, allow_conversion, amount, amount_usdrequiredwrite
POST /v1/agent/borrow/deleverageAgentApiDeleverageRequestAgentApiWriteResponsenonenonetarget_ltv, max_repay_amount_usd, source_asset, use_available_cash_first, allow_conversion, allow_partialrequiredwrite
POST /v1/agent/borrow/collateral/addAgentApiCollateralAddRequestAgentApiWriteResponsenonenoneasset, source_asset, allow_conversion, amount, amount_usdrequiredwrite
POST /v1/agent/borrow/collateral/removeAgentApiCollateralRemoveRequestAgentApiWriteResponsenonenoneasset, remove_all, max_ltv_after, amount, amount_usdrequiredwrite
POST /v1/agent/conversions/quoteAgentApiConversionQuoteRequestAgentApiConversionQuoteResponsenonenonefrom_asset, to_asset, from_vault_address, to_vault_address, slippage_percent, amount, amount_usdrequiredsimulate
POST /v1/agent/conversionsAgentApiConversionExecuteRequestAgentApiWriteResponsenonenonequote_idrequiredwrite
GET /v1/agent/conversionsAgentApiResourceListQueryAgentApiOperationsResponsenonecursor, limitnonenot requiredread
GET /v1/agent/conversions/{id}AgentApiResourceDetailQueryAgentApiOperationResponseidincludenonenot requiredread
GET /v1/agent/trusted-destinationsAgentApiResourceListQueryAgentApiRecipientsResponsenonecursor, limitnonenot requiredread
GET /v1/agent/trusted-destinations/{id}AgentApiRecipientDetailQueryAgentApiRecipientResponseidnonenonenot requiredread
DELETE /v1/agent/trusted-destinations/{id}AgentApiTrustedDestinationWriteRequestAgentApiWriteResponseidnonenonerequiredwrite
POST /v1/agent/trusted-destinations/{id}/confirmAgentApiTrustedDestinationWriteRequestAgentApiWriteResponseidnonenonerequiredwrite
POST /v1/agent/trusted-destinations/{id}/cancelAgentApiTrustedDestinationWriteRequestAgentApiWriteResponseidnonenonerequiredwrite
GET /v1/agent/recurring-paymentsAgentApiResourceListQueryAgentApiRecipientsResponsenonecursor, limitnonenot requiredread
GET /v1/agent/recurring-payments/{id}AgentApiRecipientDetailQueryAgentApiRecipientResponseidnonenonenot requiredread
POST /v1/agent/simulateAgentApiSimulateRequestAgentApiSimulateResponsenonenonemethod, path, body, depthnot requiredsimulate
POST /v1/agent/x402/signAgentApiX402SignRequestAgentApiX402SignResponsenonenonepayment_requirements, pay_to, amount, target_url, max_timeout_secondsrequiredwrite
POST /v1/agent/x402/quoteAgentApiX402QuoteRequestAgentApiX402QuoteResponsenonenoneurl, method, body, timeout_msnot requiredsimulate
POST /v1/agent/x402/purchaseAgentApiX402PurchaseRequestAgentApiX402PurchaseResponsenonenoneurl, method, body, max_amountrequiredwrite
POST /v1/agent/webhooksAgentApiWebhookCreateRequestAgentApiWebhookCreateResponsenonenoneurl, description, event_typesrequiredwebhook_management
GET /v1/agent/webhooksAgentApiResourceListQueryAgentApiWebhooksResponsenonecursor, limitnonenot requiredwebhook_management
GET /v1/agent/webhooks/{id}AgentApiResourceDetailQueryAgentApiWebhookResponseidincludenonenot requiredwebhook_management
PATCH /v1/agent/webhooks/{id}AgentApiWebhookPatchRequestAgentApiWebhookResponseidnoneurl, description, event_types, enabledrequiredwebhook_management
DELETE /v1/agent/webhooks/{id}AgentApiWebhookDeleteRequestAgentApiWebhookDeleteResponseidnonenonerequiredwebhook_management
POST /v1/agent/webhooks/{id}/rotate-secretAgentApiWebhookRotateSecretRequestAgentApiWebhookRotateSecretResponseidnonenonerequiredwebhook_management
GET /v1/agent/webhooks/{id}/deliveriesAgentApiWebhookDeliveriesQueryAgentApiWebhookDeliveriesResponseidcursor, limit, status, event_idnonenot requiredread
POST /v1/agent/webhooks/{id}/testAgentApiWebhookTestRequestAgentApiWebhookTestResponseidnonenonerequiredwebhook_management

Next#

Previous

Choosing a Tool

Next

CLI