/prices grid for routing and calls POST /firm only when a user executes a swap against your liquidity.
Endpoint map
Each chain-scoped surface implements the same five HTTP endpoints:| Endpoint | Purpose |
|---|---|
GET /tokens | Tokens you trade on this chain |
GET /pairs | Base/quote pairs Velora may route through |
GET /prices | Bid/ask grids used for cached routing |
POST /firm | Firm quote returned as a signed AugustusRFQ order |
GET /blacklist | User addresses you do not want Velora to route to you |
General requirements
All HTTP endpoints for a given chain share a common base URL. For example, both of these layouts work:- Separate hosts:
https://base.example-mm.com/tokens,https://mainnet.example-mm.com/tokens - Shared host, chain-specific paths:
https://mm.example.com/base/tokens,https://mm.example.com/mainnet/tokens
https://base.example-mm.com, https://mainnet.example-mm.com, or https://mm.example.com/base, https://mm.example.com/mainnet.
The WebSocket interface may live on a different URL, or on the same chain-scoped surface with a path such as /ws.
- Every response is JSON, including errors.
- Error responses use a 4xx or 5xx status and a body containing an
"error"string. - Any successful response may include a
"message"key alongside the payload. Velora logs it on every request, which is useful when you need diagnostics from your side to appear in integration logs. - You may additionally whitelist Velora server IPs, but the endpoints should still implement the authentication below.
Authentication (optional)
If you want Velora’s requests authenticated, exchange three credentials during onboarding:Domain— a string identifying the traffic source, so you can tell Velora apart from other integrations and, if you want, distinguish production from staging.Access Key— a passcode Velora echoes back in request headers for a quick origin check. Per-domain, and shared with no one but Velora.Secret Key— the key Velora uses to sign requests. Per-domain, and shared with no one but Velora.
-
Take the current timestamp in milliseconds since the Unix epoch (what
Date.now()returns in JavaScript). -
Build the signed payload by concatenating these values with no separator:
- The timestamp as a decimal string.
- The HTTP method in uppercase (
GETorPOST). - The request path, beginning with
/, e.g./prices. If your base URL itself contains a path such as/mainnet, it is included. - The query string exactly as sent, including the leading
?, or an empty string if there is none. No endpoint in this specification uses query parameters, so this is normally empty. - The request body exactly as sent (always a JSON object in this spec), or an empty string for
GETrequests.
https://example-mm.com/endpoint?key=value, the payload looks like:For WebSocket connections, the handshake is signed assuming the current timestamp, methodGET, the path of the connect URL, no query parameters, and no body. -
Compute the HMAC-SHA256 of that payload in hexadecimal, keyed with the Secret Key:
-
Attach the headers:
X-AUTH-DOMAIN— the DomainX-AUTH-ACCESS-KEY— the Access Key for that DomainX-AUTH-TIMESTAMP— the timestamp used in the signatureX-AUTH-SIGNATURE— the HMAC-SHA256 from the previous step
GET /tokens
Lists every token you trade on this chain. The response has a"tokens" object keyed by Token ID. A token symbol is a good ID when it is unique within the chain-scoped surface.
Most fields are informational, but address, decimals, and type need to be correct for routing and amount handling.
symbol(string) — the token’s symbol, normally matching the token contract.name(string) — the token’s full name, normally matching the token contract.description(string) — free-form notes, e.g. flagging a token deprecated in favor of another.address(string) — the token contract address. Case is ignored and normalized to lowercase on Velora’s side.decimals(number) — the token’s decimals, normally the value returned by the contract’sdecimals()method.type(string) — only"ERC20"is supported for market making today. The AugustusRFQ contract itself also settlesERC721andERC1155orders, so other types may be enabled later.
GET /pairs
Lists the trading pairs you support, or have recently disabled, on this chain. Each pair points to two Token IDs from/tokens and includes a rough USD liquidity estimate. Velora uses that estimate when it searches for routes between tokens.
Quote each pair in one direction only. Velora derives reverse pricing from the same grid.
The response has a "pairs" object keyed by Pair ID. The recommended Pair ID format is BASE/QUOTE, e.g. WETH/USDC.
base(string) — Token ID of the base token, the one bids and asks are denominated in.quote(string) — Token ID of the quote token, the one prices are given in.liquidityUSD(number) — an estimate of the liquidity backing this pair in US dollars. One way to compute it: the maximum you are willing to sell in both tokens, converted to USD and summed.
GET /prices
Returns the full bid/ask grid Velora should cache for routing. This endpoint is the live pricing source for indicative routes;POST /firm is only called later, when a user is ready to execute.
The response has a "prices" object keyed by Pair ID. Each pair may contain "bids", "asks", or both:
- Omitting
"bids"disables trading in the bid direction and clears that cached side. - Omitting
"asks"disables trading in the ask direction and clears that cached side. - Returning an empty object,
{}, disables the pair entirely.
"bids" and "asks" are arrays of [price, amount] tuples. price is the price of one base token in quote-token terms. amount is the base-token quantity available at that level. Both values are strings, and Velora parses them with bignumber.js so decimal precision is preserved.
Velora consumes each side in array order until the requested amount is reached. Put the best price first and worsen from there. The generic RFQ harness rejects crossed books, where the highest bid is greater than or equal to the lowest ask, so keep the best ask above the best bid.
- A user selling 1.5 WETH receives
1540 * 0.5 + 1500 * 1 = 2270USDC, an average price of1513.333. - A user buying 10 WETH spends
1560 * 1 + 1580 * 1.5 + 1600 * 2 + 1650 * 5.5 = 16205USDC, an average price of1620.5.
1 / price, and each amount becomes price * amount. It then applies the same fill process.
To retire a pair, don’t drop it from /pairs immediately. Keep it listed and serve {} for its prices for a period, as WETH/USDT above, then remove it.
If this endpoint fails or returns an error, Velora temporarily disables your market making on that chain. That behavior is also the off switch: serve an error here when you want to stop trading for a while.
POST /firm
Returns a firm quote as a signed order for the AugustusRFQ contract. Within Velora, the order’staker is set to a Velora execution contract (Augustus v6.2 or one of its executors, depending on execution context), and the actual user (the msg.sender to the router) is encoded in the nonceAndMeta field. Velora’s contracts always check that the user and the metadata match when filling through AugustusRFQ. That has two effects: nobody can steal the order from the user it was quoted for, and a firm quote always burns a real user address, so an address that spams firm quotes without executing can be blacklisted.
The request body:
makerAsset(string) — address of the token you (the maker) are selling.takerAsset(string) — address of the token the taker is selling.makerAmountortakerAmount(string) — the traded amount of the maker or taker asset, as an integer scaled by token decimals. Exactly one is given; you compute the other from your current prices.userAddress(string) — the end user’s address, as described above.takerAddress(string) — the Velora contract that will fill the order. Velora picks it per execution context; the current whitelist for a chain is athttps://api.velora.xyz/adapters/contract-takers?network={chainId}, and the contracts themselves are listed on Chains & contracts.
"order" object:
nonceAndMeta(string) — auint256encoding the user’s address in the lower 160 bits, with the rest filled with random or unpredictable data. Convert the address to an integer and add a random integer below2**96shifted left by 160 bits:(random.randint(0, 2**96 - 1) << 160) + int(address, 16).expiry(number) — Unix timestamp in seconds after which the order is no longer executable. At least 2 minutes in the future.makerAsset(string) — as passed in.takerAsset(string) — as passed in.maker(string) — the address holding your funds. It must approve the AugustusRFQ contract, not Augustus v6.2, to spend the maker token. It is the order’s signer if it’s an EOA; otherwise it’s a smart contract implementing EIP-1271.taker(string) — the contract that fills the order, taken from the request’stakerAddress.makerAmount(string) — as passed in, or computed from the taker amount.takerAmount(string) — as passed in, or computed from the maker amount.signature(string) —0xfollowed by lowercased hex bytes: thebytessignature AugustusRFQ expects. The order hash over all fields above is computed with EIP-712 and signed by an EOA or via an EIP-1271 contract signature.
userAddress is blacklisted, return a successful response without the "order" key. You may include a "message" explaining the blacklisting. Velora then caches the address as blacklisted, exactly as if it had come from the /blacklist endpoint.
Use this response shape only for blacklisted users. Other failures should return an error response.
The generic RFQ harness currently validates direct
/firm calls with an order-bearing response. For harness runs, rely on /blacklist to test blacklisted users and test this no-order /firm shortcut separately. See Testing your integration.GET /blacklist
Lists the user addresses you currently blacklist. The response has a"blacklist" array with no duplicate addresses:
WebSocket connection (optional)
You may additionally serve a WebSocket interface: a one-way channel from you to Velora that delivers cache updates more efficiently than polling. Each message is a JSON object that can carry any HTTP payload except"order". After the first message, send only updates: created entries, changed entries, or price removals. Do not send deletions for tokens or pairs over the WebSocket.
tokens— newly supported tokens or corrections to existing ones.pairs— newly added pairs or corrections. UpdatingliquidityUSDover WebSocket is pointless; it isn’t read from this source and changes constantly anyway.prices— pairs whose prices need updating, refreshing in the cache after going stale, or removal from the cache (bids, asks, or both).blacklist— newly added addresses only.message— anything you want logged on Velora’s servers, at any time.
/tokens, /pairs, /prices, and /blacklist in a single JSON object. That lets Velora start with a synchronized cache without making separate HTTP requests. /blacklist is still polled periodically afterwards, because blacklist status is only cached temporarily.
To stop trading entirely, disconnect the WebSocket and refuse reconnections until you want to resume.