Skip to content
Guides

Conventions

Every endpoint is under https://api.hyperstream.dev/v2/. The /v2 prefix is a fixed part of the path, not a version you can change or leave out. The same routes without it return a plain-text 404 Not Found.

The rest of these docs write paths as /v2/….

  • Bodies are JSON. Send Content-Type: application/json on POST requests.
  • Quotes and builds are single-use answers. Do not cache them.
  • Every response carries an x-request-id header (a UUID). Log it. When you contact Khalani about a request, include it with the orderId and the time of the call.

Every amount is a decimal string of integer base units, never a JSON number. On a 6-decimal token, "1000000" is 1.0. Request amounts must match ^[1-9]\d*$.

Each amount is in the base units of one token on one chain, and decimals can differ between chains for the same token. Read decimals from GET /v2/params rather than assuming.

Fields Denominated in
spend.amount, amount, srcAmount, minSrcAmount, maxSrcAmount, srcAmountSpoke, protocolFee, fullFee, refundSource, accruedFee The source token
receive.amount, outcomeAmount, maxOutcomeAmount, settledOutcome The destination token
depositFee, withdrawFee (in GET /v2/params) The listed token itself
intentOutcomeRate Not an amount: a rate, destination per source unit, scaled by 10^18
terms.flatFee (inside a quote’s build) Not a display amount: 18-decimal hub units. Pass it back unchanged

A few fields are plain JSON numbers: chain ids, decimals, seq, operatorBps, commissionBps, orderTtl, and response timestamps (at, deadline). build.terms.expiresAt in a quote is a string of Unix seconds. Pass it back unchanged.

  • Tokens are identified by chain id plus contract address, never by symbol.
  • EVM addresses come back checksummed from /v2/params and /v2/quote, and lowercase in orders. Compare addresses case-insensitively.
  • TRON addresses come back in base58. The API accepts base58 or hex41.
  • depositor is always an EVM address. Send it lowercase or exactly EIP-55 checksummed; any other mixed case is a 400.

Errors come in four JSON shapes. Only the first has an error key, so log error ?? message.

Source Body
The route itself (most 4xx/5xx) { "error": string, "detail"?: object }
Request validation { "message": "Validation failed", "name": "ValidationException", "details": [{ "field", "message", "code" }] }
Malformed JSON, maintenance, unhandled 500 { "message": string, "name": string }
Rate limit { "errorCode": "RATE_LIMITED", "message": string }

An unknown path, such as one missing the /v2 prefix, returns a plain-text 404 Not Found, not JSON. See Errors and retries for what each status means and whether to retry.