Skip to content
API v1 is deprecated. It stays supported, but new integrations should use the Khalani API. See Migrate to v2.
API v1 · Deprecated

Integration guide (v1)

v1 is non-custodial. The user signs and sends the deposit from their own wallet. Your integration requests quotes, runs the wallet actions the API returns, and tracks the order until it is final.

It suits wallets and apps that offer cross-chain swaps, aggregators that want another route source, and backends that coordinate quoting, deposits and status for a UI.

  1. Quote. POST /v1/quotes returns a quoteId and routes[].
  2. Build. POST /v1/deposit/build with { from, quoteId, routeId } returns the deposit plan: wallet actions in approvals[], or a deposit address.
  3. Execute. The user’s wallet runs approvals[] in order. See Wallet execution.
  4. Submit. PUT /v1/deposit/submit with { txHash, quoteId, routeId } returns the orderId.
  5. Track. Poll GET /v1/orders/by-id/{orderId} until the status is filled, refunded or failed.
sequenceDiagram
    participant B as Your app
    participant W as User's wallet
    participant K as API v1
    B->>K: POST /v1/quotes
    K-->>B: quoteId + routes[]
    B->>K: POST /v1/deposit/build
    K-->>B: approvals[]
    B->>W: switch chain, approve, deposit
    W-->>B: deposit txHash
    B->>K: PUT /v1/deposit/submit
    K-->>B: orderId
    B->>K: GET /v1/orders/by-id/{orderId}

A route is one way of executing the order. Route ids are literal and case-sensitive.

routeId type Covers
Hyperstream native-filler The native route: the order settles through Khalani.
HyperstreamUTXO liquidity-router The native route for trades with TRON or Bitcoin on either side.
Across external-intent-router Across.
DeBridge external-intent-router deBridge.
Glacis external-intent-router Glacis. Exact-output quotes are found by searching for the matching input (exactOutMethod: "adaptive").

The native route wins when it quotes. If Hyperstream or HyperstreamUTXO returns a quote, it is the only route in the response, even when an external route would pay more. External routes appear only when no native route quotes. An explicit list in ?routes= turns the preference off, so to compare routes yourself, name them there, for example ?routes=Hyperstream,Across,DeBridge. Most responses therefore carry one route, and picking routes[0] is a sound default.

Send fromAddress when you know the wallet that will deposit. That is the normal case:

  • With fromAddress, every route can quote, and the quote is bound to that wallet. The build must use the same address in from; any other address returns 400.
  • Without fromAddress, Across, deBridge and Glacis do not quote. The native route returns an indicative quote. To build it, pass from. The native route then prices it again for that wallet and returns 400 if the price moved, or otherwise a buildId that the submit must send back.

Each route lists the methods it accepts in depositMethods. Ask for one with depositMethod on the build. If you leave it out, the build uses the route’s only method, or CONTRACT_CALL when there are several.

Method The user Then
CONTRACT_CALL Signs the wallet actions in approvals[]. You submit the deposit’s hash.
TRANSFER Sends a plain transfer to a deposit address, from any wallet. No submit. Track with GET /v1/orders/{refundTo}?orderIds={orderId}.
TRANSFER_WITH_TX_HASH_SUBMIT Sends a plain transfer to a deposit address on TRON or Bitcoin. You submit the transfer’s hash.

The native route offers TRANSFER on some EVM source chains, next to CONTRACT_CALL. A TRON or Bitcoin source uses TRANSFER_WITH_TX_HASH_SUBMIT. PERMIT2 is in the schema, but no route offers it, and asking for it returns 400. See Deposit for the response of each method.

  • On the native route (Hyperstream), the deposit goes into Khalani’s deposit contract on the source chain, and the order is published as an intent carrying the quoted output, the recipient, the refund address and a deadline (validBefore). A filler pays the user on the destination chain. If no filler does before the deadline, the order moves to refund_pending, and to refunded once the cross-chain refund message is delivered and the deposit is returned to the refund address on the source chain. How Khalani works and the trust model describe the hub and the parts you trust.
  • On HyperstreamUTXO, a TRON or Bitcoin source has no deposit contract, so the user transfers to a deposit address and an operated service credits it.
  • On an external route, the deposit goes into that protocol’s contracts, and the protocol fills or refunds the order under its own rules. The API builds the transaction and tracks the order; it does not hold the funds.

v1 takes no API key. If Khalani gave you an integrator id, send it as the X-Integrator-Id header on POST /v1/quotes. It selects your fee configuration and is recorded on the quote and the order. The build and the submit read it from the stored quote, so they need no header.

  • The id is not authentication. A malformed header is ignored, and an unknown or disabled id falls back to the default fees.
  • The body field integratorId is the older form. When both are sent, the header wins.
  • To take a referrer fee on a single quote, send referrer and referrerFeeBps. Only the native route applies them. See Quotes.
  • Respect quoteExpiresAt. Do not build or deposit on an expired quote. Quote again instead.
  • Run approvals[] in order, one at a time. Wait for a receipt wherever waitForReceipt is true. A deposit sent before its approval confirms reverts.
  • Submit each deposit once. A repeated submit returns 404, because the quote is consumed when the order is created.
  • Track every order until it is final. Show refund_pending as “refund on its way”, not as a failure, and tell the user where the refund goes.
  • Retry by error type. See Handling exceptions.
  • There is no testnet. https://api.hyperstream.dev is the only environment. Test with small amounts.