# Getting Started - API v3

Taker API V3 is a REST API, similar to Taker API V2.

This section will walk you through the required steps to add Hashflow as a liquidity source for your platform. This could be an aggregator, an algorithmic trading bot, or any software intended to run trades against Hashflow liquidity.

## 1. Set up authentication

Hashflow authenticates all incoming requests based on the `source` field (passed in the requests below). This helps us track usage, as well as prevent DDoS attacks.

The first step in setting up your taker is [reaching out to the Hashflow team](https://forms.gle/EEzfL59vQaTebAXN9), in order to have credentials generated. Depending on the type of taker, the team will provide you with different types of credentials.

#### A. Aggregators / API Multi-Wallet Traders

This type of API integration is viable for takers such as aggregators (e.g. `1inch`, `paraswap`). The team will provide you with two important pieces of information:

* your `source` name
* the authentication key for your `source`

#### B. API Wallet Traders

This type of API integration is viable for individual takers that generally rely on one or very few wallets (e.g. retail traders, funds).

The team will provide you with an authentication key that is bound to the wallet you will be using to access the API.

### Authenticating requests

Regardless of the integration type, you have to submit a header with each request:&#x20;

`Authorization: <generated credential key>`

This, in conjunction with your identity parameters, will authenticate your request. For identity, parameters, the type of integration matters.

#### A. Aggregators / API Multi-Wallet Traders

&#x20;You will have to provide the `source` field to every request (`GET` or `POST`).

#### B. API Wallet Traders

You will have to set `source: 'api'` to every request, and also send a field named `wallet` which is populated with your wallet address (e.g. `0x01ae...b3`).

## 2. Query `/market-makers`

Next, you will need to query which market makers (liquidity sources) are currently available on Hashflow for a given network. You can do this by sending the following HTTP REST request:

```
GET https://api.hashflow.com/taker/v3/market-makers
  ?source=<source>
  &baseChainType=<string> # use 'evm' for EVM chains 
  &baseChainId=<string>   # Chain ID
  &marketMaker=<string>   # Optional
```

OR, for single wallet traders

```
GET https://api.hashflow.com/taker/v3/marketMakers
  ?source=api
  &baseChainType=<string>    # use 'evm' for EVM chains
  &baseChainId=<string>      # Chain ID
  &wallet=<wallet-address>
```

* For `<source>` use your source identifier (e.g. `my_aggregator`) or `api`
* For `<baseChainType>` use either `evm | solana`
* For `<baseChainId>` use your network ID (e.g. `1` for Ethereum, `137` for Polygon, `1000001` for Solana).
* For `<wallet>` use the `0x` -prefixed wallet address (only populate when you are single wallet traders)
* Make sure you also use the header that authenticates your source

The response to this request includes all available market makers on that chain and has format

```javascript
{
  marketMakers: string[]
}
```

For example: `{marketMakers: ['mm1', 'mm2']}`.

You'll want to re-run this request periodically for each chain so that you can tell which market makers are available.

## 3. Query Price Levels (for price discovery)

In order to understand indicative order flow, we expose price levels for the different market makers. These levels tell you, at any given time:

* what pairs are available for a given network (chain)
* how much liquidity is available for each particular pair
* what the rough prices will be once you query signed quotes for those pairs

In general, this step will allow you to do price discovery (which is inexpensive), before requesting signed quotes (which is more expensive).

The price levels APIs benefit from caching and can be queried frequently (e.g. every second).

You can get those by querying:

<pre><code><strong>GET https://api.hashflow.com/taker/v3/price-levels
</strong>  ?source=&#x3C;source>
  &#x26;baseChainType=&#x3C;string>
  &#x26;baseChainId=&#x3C;string>
  &#x26;marketMakers[]=&#x3C;mm1>
  &#x26;marketMakers[]=&#x3C;mm2>
  &#x26;baseToken=&#x3C;token address> //optional
  &#x26;quotToken=&#x3C;token address> //optional
  
</code></pre>

OR, for single wallet traders

<pre><code><strong>GET https://api.hashflow.com/taker/v3/price-levels
</strong>  ?source=api
  &#x26;wallet=&#x3C;string>
  &#x26;baseChainType=&#x3C;string>
  &#x26;baseChainId=&#x3C;string>
  &#x26;marketMakers[]=&#x3C;mm1>
  &#x26;marketMakers[]=&#x3C;mm2>
  &#x26;baseToken=&#x3C;token address> //optional
  &#x26;quotToken=&#x3C;token address> //optional
</code></pre>

This endpoint allows you query levels for an arbitrary number of market makers.

You will then get a response of the following format:

```javascript
{ 
  status: "success" | "fail",
  baseChain: {
    chainType: "evm" | "solona",
    chainId: number,
  }
  levels: Record<
    string, // They key is the market maker name
    Array<{
      pair: {
        baseToken: string,  // The address of the base token
        quoteToken: string,  // The address of the quote token
        baseTokenName: string,  // The name of the base token (e.g. ETH)
        quoteTokenName: string,  // The name of the quote token (e.g. USDC)
      },
      // string representation of the level e.g. (2.5 for 2.5 ETH)
      levels: {
        // string representation of the level (e.g. for 2.5 ETH, this will be "2.5")
        q: string,
        
        // string representation of the price per unit at that level 
        // (e.g. 3500 for "up to 2.5 ETH at 3500 USDT per ETH")
        // this price is not in decimals -- it's the actual exchange rate, 
        // in floating point notation
        p: string
      }[]
    }>
  >
}
```

Things to note:

* for each market maker, there will be one entry in the top level array for each supported pair
* levels and prices are not in decimals (e.g. 1 means 1 ETH and not 1 WEI)
* for native tokens (e.g. AVAX on avalanche, ETH on ethereum) Hashflow uses the 0 address (`0x00..00`)

Each level represents up to how much liquidity can be accessed at a given price. Also, the first level represents the minimum amount that the market maker is willing to take a quote for.

For example, suppose our levels for `ETH-USDC` are

* `{ level: "0.5", "price": "3000" }`
* `{ level: "1.5", price: "3000"}`
* `{ level: "5", price: "2999"}`

This tells us the following:

* the trader needs to sell at least `0.5 ETH`
* the trader can sell up to `7 ETH`
* the first `2 ETH` will be sold at a price of `3000 USDC`
* the next `5 ETH` will be sold at a price `2999 USDC`

For example, if the trader wants to sell `3 ETH` they will get `2 * 3000 + 2999 = 8999 USDC`

Note that, in general, as liquidity goes up, rates go down. This is expected, as market maker prices generally mirror Centralized Exchange order books.

### Cross-Chain price levels

In order to get cross-chain price levels, simply add `quoteChainType, quoteChainId` as a parameter, indicating the destination Chain ID and type for the cross-chain trade.

For example:

<pre><code><strong>GET https://api.hashflow.com/taker/v3/price-levels
</strong><strong>  ?source=&#x3C;source>
</strong>  &#x26;baseChainType=&#x3C;evm or solana>
  &#x26;baseChainId=&#x3C;chain-id>
  &#x26;quoteChainType=&#x3C;evm or solana> //optional
  &#x26;quoteChainId=&#x3C;chain-id> //optional
  &#x26;marketMakers[]=&#x3C;mm1>
  &#x26;marketMakers[]=&#x3C;mm2>
</code></pre>

## 4. Query `/rfq`

By this point, you should have an index of what market makers are available on each chain and which trading pairs they offer, as well as prices they are offering. The next step is to request a signed quote that is ready for execution.

This can target specific market makers, or be sent to all available market makers.

This request will look like:

<pre class="language-javascript"><code class="lang-javascript">POST https://api.hashflow.com/taker/v3/rfq

// JSON body
{
  source: string, // Your identifier (e.g. "1inch", "zerion")
  baseChain: {
    chainType: string, // evm | solana
    chainId: number
  }
  quoteChain: {
    chainType: string, // evm | solana
    chainId: number
  }
  rfqs: {
    // Contract address (e.g. "0x123a...789")
    baseToken: string,
    // Contract address (e.g. "0x123a...789")
    quoteToken: string,
    // Decimal amount (e.g. "1000000" for 1 USDT)
    baseTokenAmount: ?string 
    // Decimal amount (e.g. "1000000" for 1 USDT)
    quoteTokenAmount: ?string,
    // The address that will receive quoteToken on-chain.
    trader: string,
    // The wallet address of the actual trader (e.g. end user wallet).
    // If effectiveTrader is not present, we assume trader == effectiveTrader.
    effectiveTrader: ?string,
    // The wallet address to claim trading rewards for api user.
    // Cannot be set unless source == 'api'
    // This is useful when api users needs a separate wallet to claim rewards
    // If left empty, rewards will be sent to trader address
    rewardTrader: ?string,
    
    marketMakers: ?string[], // e.g. ["mm1"]    
    excludeMarketMakers: ?string[],
<strong>    options:{
</strong>      doNotRetryWithOtherMakers: ?boolean, //Default to false
    }
    
    // The amount to be charged in fees, in basis points.
    feesBps: ?number
  }[],
  calldata: ?boolean, // If this is true, contract calldata will be provided.
}
</code></pre>

Sometimes, the received quote may be coming from a market maker that does not follow the `marketMakers` field requirements. This is because the initial market maker failed to provide a request and the API fallback picked the next best market maker. In order to avoid this behavior and skip retries, you can set the `doNotRetryWithOtherMakers` flag within the `options`field for each RFQ.

If you're a Wallet API trader, the `trader` field will be used in lieu of the `wallet` field, which does not need to be passed. However, you still need to pass `source:api` in order to avoid rate limits.

You will then get a response of the following format:

```javascript
{
  status: 'success' | 'fail',
  error?: string,
  rfqId: string,  // Unique RFQ identifier
  internalRfqIds: ?string[] 
  
  quotes?: {
    quoteData: {
      baseChain: {
        chainType: string, // evm | solana
        chainId: number
      }, 
      quoteChain: {
        chainType: string, // evm | solana
        chainId: number
      },
      baseToken: string,
      baseTokenAmount: string,
      quoteToken: string,
      quoteTokenAmount: string,
      trader: string,
      effectiveTrader: ?string,
      txid: string,  // Unique quote identifier. Different from RFQ ID.
      pool: string,
      dstPool: ?string,  // For cross-chain quotes, the pool on the destination chain ID
      quoteExpiry: number,
      nonce: number,
      externalAccount: ?string,
      dstExternalAccount: ?string
    },
    signature: string,
    xChainFeeEstimate: ?string,
    targetContract: ?string,
    calldata: ?string
    value: ?string
    hftTradingRewards: ?string
  }[],
}
```

## 5a. Execute quote on-chain (EVM)

Once you have obtained a signed quote and decided to execute it, you can submit it on-chain to the [`HashflowRouter`](https://github.com/hashflownetwork/x-protocol/blob/main/evm/deployed-contracts/IHashflowRouter.json) contract via the `tradeRFQT` call.

The call is meant to be composable. However, since it is most often composed with AMMs that have slippage, the Hashflow contracts allow you to tune the token amounts in order to account for slippage (see the description of `maxBaseTokenAmount` below).

`HashflowRouter` Contract: <https://github.com/hashflownetwork/x-protocol/blob/main/evm/deployed-contracts/IHashflowRouter.json>

ABIs: <https://github.com/hashflownetwork/x-protocol/blob/main/evm/abi/IHashflowRouter.json>

Some clarification for the ABI fields:

* **`externalAccount`**. External account address. Set to `eoa`, if set in your signed quote. Otherwise, use `0x0000000000000000000000000000000000000000` address.
* **`maxBaseTokenAmount`** **/** **`maxQuoteTokenAmount`** : These are what you receive in the API as `baseTokenAmount` / `quoteTokenAmount`. Sometimes you can receive a quote for higher than what you requested. It is essential that you use the requested amount in the effectiveBaseTokenAmount field.
* **`effectiveBaseTokenAmount`** : The actual swapped amount. This has to be less than or equal to `maxBaseTokenAmount`. We suggest to keep them equal unless there's a discrepancy with the requested amount. If the `effectiveBaseTokenAmount` is less than `maxBaseTokenAmount`, the exchange rate `maxQuoteTokenAmount / maxBaseTokenAmount` will be preserved and applied to `effectiveBaseTokenAmount`
* **`value`**: If the baseToken is the native token (e.g. ETH on Ethereum), the `effectiveBaseTokenAmount` needs to be passed as `value` to the contract call

You can use *Etherscan* (or similar tools for non-Ethereum chains) to confirm the trade went through.

### Executing cross-chain quotes

Cross-chain quotes are executed via our interoperability partner, Wormhole. Wormhole operates with 2 parties:

* a set of Guardians to attest the transaction
* a Relayer on the destination chain

Both of these entities could charge a small fee. However, once the transaction is submitted on the source chain, they will take care of execution on the destination chain.

Therefore, a fee has to be paid by the trader on the source chain, in the source chain's native token (e.g. ETH for Ethereum). This fee will pay for:

* Guardian fees
* Relayer fees
* Gas fees on the destination chain

The fee that needs to be paid for each quote is returned in the `rfqs` response's `xChainFeeEstimate` field.

The amount provided is in WEI (decimals -- usually `10^-18`).

Once we have a quote, as well as a fee estimate, we can go ahead and submit the quote for execution via the `tradeXChainRFQT` contract call.

## 5b. Execute quote on-chain (Solana)

The Hashflow program address is `CRhtqXk98ATqo1R8gLg7qcpEMuvoPzqD5GNicPPqLMD`.

This is an Anchor program with a publicly available IDL. The method that should be called for trading is `trade` .

Parameters:

* `txid` - unique identifier of the quote received from the RFQ endpoint
* `tokenFromAmount`- the `baseTokenAmount` received from the API
* `tokenToAmount` - the `quoteTokenAmount`received from the API
* `quoteExpiry`- as received from the API; the unix timestamp (in seconds) when the quote will expire and be rejected on-chain
* `signature` - the first 64 bytes of the `signature`field received from the API
* `recoveryId` - the last byte of the `signature`field received from the API
* `minTokenFromAmount` - always set to `0`
* `effectiveTokenFromAmount` - can be anything between `0` and `tokenFromAmount` ; used for cases where the actual swapped amount is less than `tokenFromAmount` (useful if the exact amount is not known a priori, due to slippage); the exchange rate of `tokenToAmount` `tokenFromAmount` is preserved when pro-rating the `tokenToAmount`&#x20;

Accounts:

* `payer`- transaction payer
* `trader` - the authority of the account that is debited the `tokenFrom` ; this can be different from the authority of the account that gets credited the `tokenTo`; that authority is specified as the `trader`field in the API request, which can be unrelated to this `trader`account; for trivial cases, they will be equal
* `tokenFromMint` - `baseToken`from the API
* `tokenToMint`  -`quoteToken` from the API
* `pool` - from the API
* `tokenFromTraderAccount` - the trader token account that is debited; the authority must be the `trader`account above
* `tokenFromPoolAccount` - ATA of the `pool`for `tokenFrom`
* `tokenToTraderAccount` - the token account that is credited; the authority has to match the `trader`field in the RFQ API request (does not need to match `trader`account above)
* `tokenToPoolAccount` - ATA of the `pool`for `tokenTo`&#x20;
* `systemProgram`
* `tokenProgram`
* `associatedTokenProgram` &#x20;

It is possible to request the calldata directly by specifying the `calldata: true` field in the RFQ endpoint, however it comes with some assumptions which may not be ideal:

* `payer` = `trader`&#x20;
* the authority of the `tokenFromTraderAccount`matches the authority of `tokenToTraderAccount`

## 6. Query `/restrictions`

Market makers can set `rate_limit` on given a trader and a network. All `rate_limit` restrictions will have an expiry window, which means traders can re-gain access to the market maker after the specified expiry time. To understand the restriction status, takers can query `/restrictions` endpoint to better understand error messages from market maker and adjust routing accordingly. When a trader has been restricted, we will automatically route their RFQs to other makers (if present) until restriction expires.&#x20;

We suggest you use the response you get from this endpoint to display proper error message as well as route your RFQs requests to other available makers accordingly.&#x20;

For example:&#x20;

```
GET https://api.hashflow.com/taker/v3/restrictions?source=<your-source>&trader=<0x...>&chainId=<chainId>&chainType=<chainType>
```

&#x20;The response will be in the following shape &#x20;

```
{ 
  isTraderRestricted: boolean; 
  restrictions?: Array<{ 
    reason: 'rate_limit'; 
    expiryTimestampMs?: number; //UTC milliseconds timestamps
    marketMaker?: string; 
    chainId?: string
    chainType: string
  }> 
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.hashflow.com/hashflow/taker/getting-started-api-v3.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
