# hive-swap API — full reference > Stateless DEX aggregator and bridge for Hive Engine. The API returns unsigned Hive > `custom_json` operations and native Hive transfer ops; the caller signs and broadcasts. > The API never sees private keys. Base URL: https://api.hive-swap.com Rate limit: 30 requests/min per IP. No auth. Platform fee: 0.25% (25 bps) of the input amount, collected automatically by the returned ops. ## Response envelope ```json { "ok": true, "data": ...payload } { "ok": false, "error": { "code": "INVALID_INPUT|RATE_LIMITED|NO_ROUTE|BELOW_MIN|NOT_FOUND|UPSTREAM|INTERNAL", "message": "..." } } ``` CORS: all responses include `Access-Control-Allow-Origin: *`. --- ## GET /health Liveness probe (not rate limited). Response: ```json { "ok": true, "data": { "status": "ok", "service": "hive-swap-api", "version": "v1", "time": "2026-05-11T12:00:00.000Z" } } ``` --- ## GET /tokens All Hive Engine tokens. Response `data.tokens[]`: ```json { "symbol": "BEE", "name": "BEE Token", "precision": 8, "issuer": "aggroed", "icon": "https://..." | null } ``` --- ## GET /pools All Hive Engine liquidity pools (`marketpools` contract). Response `data.pools[]`: ```json { "tokenPair": "SWAP.HIVE:BEE", "baseQuantity": "...", "quoteQuantity": "...", "basePrice": "...", "quotePrice": "...", "totalShares": "..." } ``` Pool keys are `BASE:QUOTE`. The router auto-resolves direction. --- ## GET /gateways Bridge gateway info — HE peg, EVM, converter (BTC/LTC/DOGE/BCH), and HE-native (ETH/BSC/Polygon/Solana). Response `data`: ```json { "platformFeeBps": 25, "heGateways": [ { "account": "uswap", "label": "USWAP", "feePct": 0.09, "pegInMin": 1, "pegInSoftCap": 10000 }, { "account": "honey-swap", "label": "HivePegged", "feePct": 0.75, "pegInMin": 1, "pegInSoftCap": null } ], "evmBridges": [ { "chain": "base", "hiveGateway": "whive.base", "minHive": 100, "minTotalHive": 100.26, "memoFormat": "bridge:hive-base:<0xEvmAddress>" }, { "chain": "bsc", "hiveGateway": "whive.bsc", "minHive": 100, "minTotalHive": 100.26, "memoFormat": "bridge:hive-bsc:<0xEvmAddress>" }, { "chain": "eth", "hiveGateway": "whive.eth", "minHive": 1000, "minTotalHive": 1002.51, "memoFormat": "bridge:hive-eth:<0xEvmAddress>" } ], "converterBridges": [ { "coin": "BTC", "swapSymbol": "SWAP.BTC", "hiveGateway": "btc-swap", "minAmount": 0.0005, "converterApiBase": "https://...", "quoteEndpoint": "/api/v1/bridge/converter/quote", "memoFormat": "BTC " }, { "coin": "LTC", "swapSymbol": "SWAP.LTC", "hiveGateway": "btc-swap", "minAmount": 0.05, "converterApiBase": "https://...", "quoteEndpoint": "/api/v1/bridge/converter/quote", "memoFormat": "LTC " }, { "coin": "DOGE", "swapSymbol": "SWAP.DOGE", "hiveGateway": "btc-swap", "minAmount": 50, "converterApiBase": "https://...", "quoteEndpoint": "/api/v1/bridge/converter/quote", "memoFormat": "DOGE " }, { "coin": "BCH", "swapSymbol": "SWAP.BCH", "hiveGateway": "btc-swap", "minAmount": 0.01, "converterApiBase": "https://...", "quoteEndpoint": "/api/v1/bridge/converter/quote", "memoFormat": "BCH " } ], "nativeBridges": [ { "chain": "eth", "coin": "ETH", "swapSymbol": "SWAP.ETH", "hiveGateway": "swap-eth", "gatewayApiBase": "https://...", "registrationId": "...", "withdrawalFeePct": 1.0, "memoFormat": "" }, { "chain": "bsc", "coin": "BNB", "swapSymbol": "SWAP.BNB", "hiveGateway": "swap-bsc", "gatewayApiBase": "https://...", "registrationId": "...", "withdrawalFeePct": 1.0, "memoFormat": "" }, { "chain": "polygon", "coin": "POL", "swapSymbol": "SWAP.MATIC","hiveGateway": "swap-polygon", "gatewayApiBase": "https://...", "registrationId": "...", "withdrawalFeePct": 1.0, "memoFormat": "" }, { "chain": "solana", "coin": "SOL", "swapSymbol": "SWAP.SOL", "hiveGateway": "swap-solana", "gatewayApiBase": "https://...", "registrationId": "...", "withdrawalFeePct": 1.0, "memoFormat": "" } ] } ``` `minTotalHive` = the minimum HIVE amount you must pass to `/bridge/in/build` for that EVM chain (covers the 0.25% platform fee so the gateway still receives ≥ `minHive`). `converterBridges` and `nativeBridges` advertise gateway info for chain pegs that don't yet have a dedicated `/build` endpoint. To use them: for converter peg-in call `POST /bridge/converter/quote` (returns a chain-specific deposit address). For converter peg-out and all HE-native peg-out, sign a Hive Engine `tokens.transfer` of the SWAP.X token to `hiveGateway` with `memoFormat` as the memo. You still owe the 0.25% platform fee on a separate `tokens.transfer` to `hive-swap-fees` — match the pattern in `/bridge/out/build`. --- ## POST /quote Get a swap quote. `GET` with the same query params is also supported. Request body: ```json { "fromSymbol": "SWAP.HIVE", "toSymbol": "BEE", "amount": "10", "slippagePct": 1, "username": "alice" } ``` - `amount` is a positive numeric string (no scientific notation). - `slippagePct` is in percent. 0–50. Defaults to 1 if omitted. - `username` is optional. When supplied, the route is BEED-aware: if the account holds < 0.002 BEED, book-routed legs are stripped and a pool-only quote is returned (because HE's `market.*` ops would revert at the BEED multi-tx fee — see below). Omit `username` to get the raw best-output route regardless of any account's holdings. Either way, `/swap/build` always honors the BEED check on its own required `username`, so a `/quote` without `username` may show a higher `amountOut` than `/swap/build` will actually produce for the same user. Response `data.quote`: ```json { "route": [{ "tokenIn": "SWAP.HIVE", "tokenOut": "BEE", "amountIn": "10", "amountOut": "...", "poolPair": "SWAP.HIVE:BEE", "poolPortion": { "amountIn": "6", "amountOut": "...", "poolPair": "SWAP.HIVE:BEE" }, "bookPortion": { "amountIn": "4", "amountOut": "...", "side": "buy", "worstPrice": "...", "limitPrice": "...", "levelsConsumed": 3, "fullyFilled": true } }], "amountIn": "10", "amountOut": "...", "priceImpact": "0.0123", "minAmountOut": "..." } ``` Each step's execution may be split between an AMM pool (`poolPortion`) and the HE order book (`bookPortion`). When both are present, the router has determined (via ternary search) that the split gives a better effective price than either alone. The legacy top-level `poolPair` field on a step is kept for backwards compatibility and mirrors `poolPortion?.poolPair` — new integrations should read the portions. `bookPortion.side` is `"buy"` when buying a non-HIVE base symbol (= `tokenOut`) with SWAP.HIVE, and `"sell"` in the reverse direction. `bookPortion.limitPrice` is the worst price you'll accept on that leg; HE matches at the maker's price. The router searches the full pool graph up to 3 hops and returns the route with the highest output after fees — this may be a longer route than the obvious direct one when an arbitrage path is more efficient (e.g. `SWAP.HIVE → SWAP.EOS → BEE → LEO` can beat the direct `SWAP.HIVE:LEO` pool by several percent at certain moments). Dead pools (zero reserves on either side) are skipped. Order books only apply to SWAP.HIVE-paired legs (an HE protocol constraint), so longer routes that touch SWAP.HIVE can still layer in book liquidity on those specific hops. A 3-hop route example for a token with no SWAP.HIVE pool: ```json { "route": [ { "tokenIn": "SWAP.HIVE", "tokenOut": "LBI", "amountIn": "10", "amountOut": "..." }, { "tokenIn": "LBI", "tokenOut": "HSBIDAO", "amountIn": "...", "amountOut": "..." } ] } ``` (For `SWAP.HIVE → HSBIDAO` that's 2 hops; from a non-HIVE source it would be 3 hops through SWAP.HIVE.) Intermediate hops use `minAmountOut = 1 satoshi` on the pool leg — only the final hop enforces the user's `slippagePct`. SWAP.HIVE is a recoverable intermediate; if a middle hop fails mid-execution the user is left holding it. Errors: - `NO_ROUTE` (404): no path within 3 hops connects the pair via pools and SWAP.HIVE-paired books. --- ## POST /swap/build Build the unsigned `custom_json` ops to execute a swap. Request body: ```json { "username": "alice", "fromSymbol": "SWAP.HIVE", "toSymbol": "BEE", "amount": "10", "slippagePct": 1 } ``` Response `data` (example shows a split route — pool + book in one hop): ```json { "quote": { ...same as /quote }, "ops": [ { "contractName": "tokens", "contractAction": "transfer", "contractPayload": { "symbol": "SWAP.HIVE", "to": "hive-swap-fees", "quantity": "0.025", "memo": "HiveSwap swap: SWAP.HIVE→BEE | r:a8f2c1", "isSignedWithActiveKey": true } }, { "contractName": "marketpools", "contractAction": "swapTokens", "contractPayload": { "tokenPair": "SWAP.HIVE:BEE", "tokenSymbol": "SWAP.HIVE", "tokenAmount": "5.985", "tradeType": "exactInput", "minAmountOut": "...", "isSignedWithActiveKey": true } }, { "contractName": "market", "contractAction": "buy", "contractPayload": { "symbol": "BEE", "quantity": "...", "price": "..." } } ], "signing": { "method": "requestCustomJson", "hiveChainId": "ssc-mainnet-hive", "keyType": "Active", "displayName": "Swap 10 SWAP.HIVE → ... BEE", "note": "Each op is one Hive Engine custom_json. ..." } } ``` The first op collects the 0.25% platform fee. Each subsequent step in the route may emit a `marketpools.swapTokens` op (pool portion), a `market.buy` or `market.sell` op (book portion), or both — they all sit in the same `custom_json` and execute atomically. Intermediate hops use minimal slippage protection on the pool leg; the final hop carries the user's `minAmountOut`. Book legs enforce slippage per-leg via `price` (= `bookPortion.limitPrice`). Pool-only quotes return only `marketpools.swapTokens` ops (no `market.*`). ### BEED requirement for order-book routes Hive Engine's `market` contract charges a multi-tx fee of **0.001 BEED per `market.buy`/`market.sell`/`market.cancel` action**, burned pre-execution by the `resourcemanager` contract. If the user has no BEED, the `market.*` op reverts at the burn step (`balance does not exist` / `not enough tokens for multiTransaction fee`). HE-tx atomicity is *per-op*, not per-Hive-tx — so the fee transfer op (`tokens.transfer` to `hive-swap-fees`) in the same Hive `custom_json` still executes, and the user loses the platform fee on every retry. The pool-only contract (`marketpools`) has no such fee. **`/swap/build` auto-routes around this.** Because `/swap/build` already takes the user's `username`, it checks BEED balance server-side and silently strips book-routed legs when the user holds < 0.002 BEED (covers a 2-hop worst case). The returned `ops` will only contain `marketpools.swapTokens` for the swap legs in that case, never `market.buy`/`market.sell`. No client-side bootstrap is required for the common case. **`/quote` is BEED-aware only when `username` is supplied.** A bare `/quote` returns the raw best-output route (book + pool as the router sees fit) — useful for displaying "best possible price" — but the user's actual buildable route may differ. Pass `username` to `/quote` to get a quote that matches what `/swap/build` will produce for that user. **The edge case where book is unavoidable**: if the pair has no AMM pool path at all (rare — typically only obscure tokens), the API returns the book route even for a BEED-less user because there's literally no other path. In that case you must either: - Tell the user to acquire BEED through any HE wallet (any amount above 0.002 unlocks the swap), or - Prepend a `beedollar.convert` op yourself in the same Hive tx: `{ "contractName": "beedollar", "contractAction": "convert", "contractPayload": { "quantity": "1" } }` — mints ~39 BEED from 1 BEE (1% fee, 1 BEE chain minimum). If the user has no BEE either, prepend a pool buy of BEE from SWAP.HIVE first. Bootstrap ops are themselves exempt from the BEED fee. You can detect this case by checking whether the returned `ops` contain any `market.buy`/`market.sell` despite supplying `username`. If so, the user needs BEED — there was no pool fallback. The HiveSwap web UI auto-detects this and offers an in-UI BEED bootstrap; third-party integrations either accept the pool-only routing (the default), tell the user to fund BEED, or prepend their own bootstrap op. ### Signing & broadcasting Browser (Hive Keychain), one prompt per op: ```js for (const op of data.ops) { await new Promise((resolve, reject) => { window.hive_keychain.requestCustomJson( data.username, 'ssc-mainnet-hive', 'Active', JSON.stringify(op), 'HiveSwap', (r) => r.success ? resolve(r) : reject(new Error(r.message)) ); }); } ``` Node (dhive), bundled into a single transaction: ```js import { Client, PrivateKey } from '@hiveio/dhive'; const client = new Client(['https://api.hive.blog']); const ops = data.ops.map(op => ['custom_json', { required_auths: ['alice'], required_posting_auths: [], id: 'ssc-mainnet-hive', json: JSON.stringify(op), }]); await client.broadcast.sendOperations(ops, PrivateKey.fromString(process.env.HIVE_ACTIVE_KEY)); ``` Errors: - `INVALID_INPUT`: bad username / symbols / amount / slippagePct. - `NO_ROUTE` (404): no swap path. --- ## POST /bridge/in/build Build ops to bridge HIVE into another chain. ### Request — `type: 'evm'` (HIVE → wHIVE on Base/BSC/Eth) ```json { "type": "evm", "username": "alice", "amount": "150", "toChain": "base", "toAddress": "0xabc..." } ``` - `toChain`: `'base'` | `'bsc'` | `'eth'`. - `amount` (HIVE) must be ≥ `minTotalHive` from `/gateways`. Otherwise → `BELOW_MIN`. - `toAddress` must be a valid 0x-prefixed EVM address. Response `data`: ```json { "gateway": "whive.base", "chain": "base", "ops": [ ["transfer", { "from": "alice", "to": "hive-swap-fees", "amount": "0.375 HIVE", "memo": "HiveSwap peg-in: HIVE→Base | r:b7e3d2" }], ["transfer", { "from": "alice", "to": "whive.base", "amount": "149.625 HIVE", "memo": "bridge:hive-base:0xabc..." }] ], "split": { "netAmount": "149.625", "feeAmount": "0.375", "totalAmount": "150.000", "feePct": 0.25 }, "estimatedReceive": "149.625", "signing": { "method": "broadcastOps", "keyType": "Active", "displayName": "Bridge 150 HIVE → wHIVE on base", "note": "..." } } ``` These are **native Hive transfer operations**, not `custom_json`. Sign as a normal Hive transaction. ### Request — `type: 'he'` (HIVE → SWAP.HIVE via uswap/honey-swap peg-in) ```json { "type": "he", "username": "alice", "amount": "5", "slippagePct": 1 } ``` Response includes `gateway`, `gatewayLabel`, `gatewayFeePct`, `ops` (two transfers), `split`, and `memo`. The router picks the cheapest gateway that has enough SWAP.HIVE to settle. ### Signing — native Hive transfers (browser) ```js window.hive_keychain.requestBroadcast(data.username, data.ops, 'Active', (r) => { /* ... */ }); ``` Node (dhive): ```js const ops = data.ops; // already in [opName, payload] shape await client.broadcast.sendOperations(ops, PrivateKey.fromString(process.env.HIVE_ACTIVE_KEY)); ``` Errors: - `BELOW_MIN`: amount below the minimum that produces a valid net transfer to the gateway. - `INVALID_INPUT`: missing/invalid `type`, `toChain`, `toAddress`, etc. --- ## POST /bridge/out/build Build ops to peg SWAP.HIVE back to native HIVE via the `hivepegged.withdraw` contract. Request body: ```json { "username": "alice", "amount": "10" } ``` `symbol` is accepted for forward-compatibility and defaults to `SWAP.HIVE`. **Only SWAP.HIVE is actually supported by this endpoint** — the underlying `hivepegged` contract is HIVE-only. Response `data.ops`: ```json [ { "contractName": "tokens", "contractAction": "transfer", "contractPayload": { "symbol": "SWAP.HIVE", "to": "hive-swap-fees", "quantity": "0.025", "memo": "HiveSwap peg-out: SWAP.HIVE→HIVE | r:c9a4b3" } }, { "contractName": "hivepegged", "contractAction": "withdraw", "contractPayload": { "quantity": "9.975", "isSignedWithActiveKey": true } } ] ``` Sign as Hive Engine `custom_json` (chain id `ssc-mainnet-hive`) with the Active key — same pattern as `/swap/build`. Note: the web UI at `/bridge` also routes SWAP.HIVE → HIVE through the cheaper `uswap` gateway when it has enough HIVE on hand. That gateway-routing path is not yet exposed by the public API — the API always returns the contract path (`hivepegged.withdraw`, 0.75% gateway fee). --- ## POST /bridge/converter/quote Register a peg-in (BTC/LTC/DOGE/BCH → SWAP.X) or peg-out (SWAP.X → BTC/LTC/DOGE/BCH) with the converter gateway. The endpoint mints a deposit address (peg-in) or returns the HE account + memo the user must transfer SWAP.X to (peg-out). No platform fee is collected here — for peg-out, the caller signs the SWAP.X transfer themselves (and the 0.25% platform fee on top, same pattern as `/bridge/out/build`). Request body: ```json { "fromCoin": "BTC", "toCoin": "SWAP.BTC", "destination": "alice" } ``` - Supported pairs (one of these two shapes): - **Peg-in:** `fromCoin ∈ {BTC,LTC,DOGE,BCH}` and `toCoin = "SWAP." + fromCoin`. `destination` must be a valid Hive account name. - **Peg-out:** `fromCoin ∈ {SWAP.BTC,SWAP.LTC,SWAP.DOGE,SWAP.BCH}` and `toCoin = fromCoin.replace("SWAP.","")`. `destination` is the external-chain address (validated upstream by the converter API, max 128 chars). Response — **peg-in** (deposit address): ```json { "ok": true, "data": { "destination": "alice", "address": "bc1q...", "gatewayAccount": "btc-swap" } } ``` Response — **peg-out** (HE account + memo to transfer SWAP.X to): ```json { "ok": true, "data": { "account": "btc-swap", "memo": "BTC bc1q...", "gatewayAccount": "btc-swap" } } ``` Errors: - `INVALID_INPUT`: unsupported pair, missing/invalid `destination`, or invalid Hive account on peg-in. - `UPSTREAM` (502): converter API unreachable or rejected the request. --- ## GET /bridge/converter/coins Static list of converter-supported coins with chain minimums and gateway info. Response `data.coins[]`: ```json { "coin": "BTC", "swap": "SWAP.BTC", "displayName": "Bitcoin", "precision": 8, "minAmount": 0.0005, "gatewayAccount": "btc-swap", "converterApiBase": "https://...", "platformFeeBps": 25, "memoFormat": "BTC " } ``` Cache: `public, s-maxage=300, stale-while-revalidate=600`. --- ## HBD ↔ SWAP.HBD (web UI only) HBD bridging uses the [DSwap](https://dswap.trade) API and the `graphene-swap` account on Hive. It is currently available only in the web UI at https://www.hive-swap.com/bridge under the **HBD** tab. There is no `/bridge/hbd/*` endpoint yet — peg-in/peg-out for HBD must go through the UI (or directly through the DSwap REST API at `https://dswap-api.dswap.trade/api`). --- ## GET /status/{ref} Bridge transaction status by reference. Used for monitoring webhook-driven flows — the same status pipeline backs the HE-native bridges advertised in `/gateways` (`nativeBridges` covers ETH/BSC/Polygon/Solana) and the converter bridges (`converterBridges` covers BTC/LTC/DOGE/BCH). The web UI is the easiest way to drive a flow that produces a `ref`. Response: ```json { "reference": "...", "status": "pending|completed|failed", "direction": "...", "hiveAccount": "...", "solAddress": "...", "solAmount": "...", "estimatedHive": "...", "hops": [...], "error": null, "createdAt": 1700000000, "updatedAt": 1700000010 } ``` --- ## GET /profile/{username} User points profile. Always returns a profile object — users with no activity get level 1 / 0 points / all badges locked rather than a 404. Points are awarded asynchronously after each successful swap (10 pts per $1 of volume) or bridge (15 pts per $1 of volume). The pipeline replays Hive Engine transaction logs to skip failed routes — only successful actions earn points. New activity typically reflects on profiles within ~5 minutes of the on-chain transaction. Path: `username` is a Hive account (lowercase). Mixed case is normalized. Response `data`: ```json { "username": "alice", "level": 12, "maxLevel": 30, "tier": { "id": "octopus", "name": "Octopus", "color": "#b85450" }, "totalPoints": 312450, "pointsIntoLevel": 45753, "pointsToNext": 57250, "currentThreshold": 266697, "nextThreshold": 369902, "lifetimeVolumeUsd": 31245.7, "swapCount": 142, "bridgeCount": 8, "firstSeenTs": 1722470000, "lastActivityTs": 1747000000, "badges": [ { "id": "tier_shrimp", "label": "Shrimp", "description": "Reach level 5", "earned": true }, { "id": "tier_crab", "label": "Crab", "description": "Reach level 10", "earned": true }, { "id": "tier_whale", "label": "Whale", "description": "Reach level 30", "earned": false }, { "id": "first_swap", "label": "First Swap", "description": "Complete your first swap", "earned": true }, { "id": "centurion", "label": "Centurion", "description": "Complete 100 swaps", "earned": true } ], "leaderboardRank": 17 } ``` **Level curve.** Cumulative points required to reach level L follow `floor(30 * (L-1)^3.8)`. Tier ceilings (using the 10 pts/$ swap rate): - Shrimp (L1-L5): up to ~$582 lifetime volume - Crab (L6-L10): up to ~$12.7k - Octopus (L11-L15): up to ~$68k - Dolphin (L16-L20): up to ~$218k - Shark (L21-L25): up to ~$528k - **Whale (L26-L30): ~$1.08M** **Badge IDs.** `tier_shrimp`, `tier_crab`, `tier_octopus`, `tier_dolphin`, `tier_shark`, `tier_whale` (tier badges); `first_swap`, `centurion` (100+ swaps), `first_bridge`, `cross_chain` (3+ distinct bridge destinations), `megalodon` ($10k+ single event), `kraken` ($100k+ single event), `og` (active during the first 30 days of the points era). Cache: `s-maxage=30, stale-while-revalidate=120`. --- ## GET /profile/{username}/activity Paginated points-earning event log for a user. Newest first. Query params: - `limit` (default 25, max 100) - `before` (optional unix timestamp — return events with `ts < before` for keyset pagination) Response `data`: ```json { "events": [ { "opId": "67d8a3c1e9b8d4a000000123", "ts": 1747000000, "kind": "swap", "volumeUsd": 124.5, "pointsEarned": 1245, "symbol": "SWAP.HIVE", "amount": "0.305", "txId": "abc123...", "source": "he", "memo": null, "routeSteps": [ { "symbol": "SWAP.HIVE", "amount": "122.0" }, { "symbol": "BEE", "amount": "..." } ] } ], "nextBefore": 1747000000 } ``` `nextBefore` is `null` when fewer than `limit` rows are returned. `routeSteps` is best-effort — `null` if the route couldn't be resolved (rare; transient RPC issue). Failed swaps appear with `volumeUsd: 0, pointsEarned: 0` so the user sees them in their history but isn't credited. --- ## GET /leaderboard Top users by total points, all-time. Time-windowed leaderboards (24h / 7d / 30d) are not yet supported. Query params: - `limit` (default 100, max 500) Response `data`: ```json { "rows": [ { "rank": 1, "username": "alice", "level": 27, "tier": { "id": "whale", "name": "Whale", "color": "#1e3a5f" }, "totalPoints": 8104225, "lifetimeVolumeUsd": 810422.5, "swapCount": 412, "bridgeCount": 28, "lastActivityTs": 1747000000 } ], "total": 1247 } ``` `total` is the global count of users with at least one point. Cache: `s-maxage=60, stale-while-revalidate=300`. --- ## Error codes | Code | HTTP | Meaning | |-----------------|------|---------| | `INVALID_INPUT` | 400 | Missing / malformed parameter. | | `NO_ROUTE` | 404 | No swap path exists for the given token pair. | | `BELOW_MIN` | 400 | Amount below the gateway's minimum (bridge endpoints). | | `NOT_FOUND` | 404 | Reference or resource does not exist. | | `RATE_LIMITED` | 429 | Per-IP rate limit exceeded. Includes `Retry-After`. | | `UPSTREAM` | 502 | Failure talking to a Hive / Hive Engine RPC. | | `INTERNAL` | 500 | Unhandled error. | --- ## Tips for integrators - **Always re-quote close to broadcast time.** Pool reserves shift and book depth turns over fast; an old `minAmountOut` or `bookPortion.limitPrice` can be too tight and revert. - **Book routes need BEED — but `/swap/build` routes around this for you.** When you pass `username`, the build endpoint strips book legs for accounts holding < 0.002 BEED and returns a pool-only build that doesn't pay the 0.001 BEED multi-tx fee. Pass `username` to `/quote` too if you want the displayed quote to match what `/swap/build` will produce. The only case you have to handle yourself is the rare pair with no pool path at all — detect by checking `ops` for `market.*` after a build with `username` set. See the `/swap/build` section. - **The platform fee is in the ops, not deducted by the API.** The first op in every build response is the fee transfer to `hive-swap-fees`. Do not strip it — your effective output assumes it ran. - **Fee transfer memos are typed and parseable.** Every fee transfer op the API emits carries a memo identifying the operation and direction: - Swap: `HiveSwap swap: {firstTokenIn}→{lastTokenOut} | r:{ref}` (e.g. `HiveSwap swap: SCRAP→SWAP.HIVE | r:a8f2c1`) - L1 peg-in: `HiveSwap peg-in: {currency}→{dest} | r:{ref}` (e.g. `HiveSwap peg-in: HIVE→Base | r:b7e3d2`) - HE peg-out: `HiveSwap peg-out: {symbol}→{dest} | r:{ref}` (e.g. `HiveSwap peg-out: SWAP.HIVE→HIVE | r:c9a4b3`) - Converter peg-in (post-arrival fee, user-signed separately): `HiveSwap peg-in fee: {symbol} | r:{ref}` `{ref}` is 6 random hex chars per build; it's there for visual de-duplication in wallet history, not for routing or analytics. To classify a transfer to `hive-swap-fees` as swap-vs-bridge, match the memo prefix: `HiveSwap swap` → swap, `HiveSwap peg` → bridge. Legacy events (pre-2026-05-13) used the static memo `HiveSwap platform fee` for bridge ops and an empty memo for swap ops; both still classify correctly. - **Bridge minimums are HARD.** Sending below `minTotalHive` to a gateway can result in funds being permanently stuck (gateway oracle ignores the transfer). The API enforces `BELOW_MIN` to prevent this — do not bypass. - **Native vs custom_json ops are different shapes.** `/swap/build` and `/bridge/out/build` return `[{ contractName, contractAction, contractPayload }, ...]` (Hive Engine custom_json). `/bridge/in/build` returns `[[opName, payload], ...]` (native Hive ops). Sign accordingly. - **Chain id for HE ops is `ssc-mainnet-hive`.** Always.