# Zecret Swap > Zecret Swap is a non-custodial private swap of any token, built on 1Click, NEAR Intents' swap API, on the confidential route. It holds no funds and no keys. An agent asks for a quote, checks it, sends one transfer from its own wallet, and follows the swap to its end. Each swap is $5 to $50,000. This file is for agents. Everything you need to use the HTTP API is here. The same facts, as an OpenAPI 3.1 document, are at https://zecretswap.com/api/openapi.json. A CLI and an MCP server do the checks for you (see "The CLI and the MCP server"). ## What Zecret Swap offers - Private swaps of any token to any token, across chains, on NEAR Intents' confidential route. - Shielded ZEC at a Unified Address that starts with u1. - Private send: a token to someone else, and your wallet never pays theirs. - Private payment links: anyone can pay with any token, and you get shielded ZEC. - A command-line tool, an MCP server and a plain HTTP API for AI agents. - Your browser checks NEAR Intents' signature on each quote before you send. - Fees: 0.4% to Zecret Swap and about 0.2% to NEAR Intents. Each swap is $5 to $50,000. No account. ## How a swap works 1. Read the tokens: `GET /api/swap/tokens`. Pick two tokens by `assetId`. 2. Ask for a dry quote: `POST /api/swap/quote` with `dry: true`. It shows what you get, the fees and the time. It holds no address of yours. 3. Ask for a live quote: the same call with `dry: false`, your payout address and your refund address. The reply holds a deposit address. 4. Check the live quote (see "Check every live quote before you send"). If any check fails, send nothing. 5. Send exactly the quoted amount of the quoted token, in one transfer, from your own wallet, to the deposit address. Optionally tell 1Click with `POST /api/deposit`. 6. Follow the swap: `POST /api/status` with the deposit address and the quote's `signature` as the `proof`, about every five seconds, until the status is SUCCESS, REFUNDED or FAILED. Zecret Swap never signs, never sends and never holds keys. Funds go from your wallet to a 1Click deposit address. If the swap cannot finish, 1Click refunds to the refund address you gave. ## Send a token to someone else Zecret Send pays one token to someone else's address: the same token, on the same chain, through NEAR Intents' confidential route. It uses the same endpoints as a swap. 1. Ask for a quote as for a swap, with `send: true`. Give the token's `assetId` as both `originAsset` and `destinationAsset`. 2. For a live quote, `recipient` is the address of the person you pay, on that chain. `refundTo` is an address of yours. 3. Check the live quote as for a swap, with one change: `originAsset` and `destinationAsset` are the one token you chose. Also check that `amountIn` less `amountOut` less `withdrawFee` is no more than 3% of `amountIn`. 4. Your wallet never pays theirs. NEAR's public record lists the deposit and the payout as separate rows, and no field links them. Both rows show the same token and nearly the same amount, so a watcher can often link them. ## The HTTP API Base URL: https://zecretswap.com Every call is JSON. A POST needs `content-type: application/json`. A browser on another site is refused with 403. A script or a server is not: it sends no `Sec-Fetch-Site` header. ### GET /api/swap/tokens Returns `{ tokens: Token[], fetchedAt, routes? }`. `routes`, when present, names routes the website offers that these docs do not cover, such as `{ zcash: true }`. A token is `{ assetId, symbol, decimals, chain, contractAddress?, price? }`. `chain` is the chain's id (`base`, `sol`, `zec`, `eth`, `btc`, `near`, and others). `price` is US dollars at 1Click's list price. A token that is not in the list is refused by the quote endpoint. The answer is cached for a minute. Tokens on `hypercore` (USDC on Hyperliquid) are payout only. Use them as `destinationAsset`, never as `originAsset`. Their minimum is about $8. ### POST /api/swap/quote Body, JSON, no other field: - `dry` (boolean, required). true for a preview with no address. false for a live quote. - `originAsset` (string, required). The `assetId` of the token you send. - `destinationAsset` (string, required). The `assetId` of the token you receive. It must differ from `originAsset`, unless `send` is true: then it is the same. - `amount` (string, required). Base units of the origin token: digits, not starting with 0. For USDC, which has six decimals, 50 USDC is "50000000". The swap must be worth $5 to $50,000. - `recipient` (string). The payout address, on the destination chain. Required when `dry` is false. A dry quote may leave it out. - `refundTo` (string). The refund address, on the origin chain. Required when `dry` is false. A dry quote may leave it out. When you pay with ZEC, use a t1… address: NEAR Intents refunds ZEC to a transparent address only, and a refund there is public. - `transparentOptIn` (boolean, default false). Allow a Zcash payout to a transparent address. It is public. - `slippageBps` (integer, one of 50, 100, 200, default 100). How far the payout may fall below the quote. - `send` (boolean, default false). true for a send: the payout goes to someone else's address, and `destinationAsset` must be the same as `originAsset`. Returns `{ quote, route, preview }`. `quote` is 1Click's signed quote, unchanged: `{ correlationId, timestamp, signature, quoteRequest, quote }`. So the deposit address is at `reply.quote.quote.depositAddress`, and the amount to send is `reply.quote.quote.amountIn`. `route` is the route the server asked for: `basic` or `advanced`, both confidential. `preview` says which addresses the server filled in for a dry quote. A live quote needs real addresses. The server checks both for their chains, and refuses a stand-in. A dry quote holds none of yours, so 1Click sees your addresses only when you ask for a live quote. Every quote asks for the confidential route. If 1Click has none for the pair, the answer is the error `no-confidential-route`. The server does not fall back to a public quote. ### POST /api/status Body: `{ depositAddress, proof? }`. `proof` is the `signature` of your live quote (`reply.quote.signature`). It shows that you asked for the quote. A deposit address is public on its chain, so the swap's details go only to the person who holds the proof. With the right proof the reply is `{ status, updatedAt, swapDetails, origin?, destination?, kind?, timeEstimate? }`. With none, or a wrong one, it is `{ status }` and nothing else, and the two replies are the same, so a guess cannot be tested. `status` is one of PENDING_DEPOSIT, KNOWN_DEPOSIT_TX, INCOMPLETE_DEPOSIT, PROCESSING, SUCCESS, REFUNDED, FAILED. The last three are final. `swapDetails` is 1Click's own: amounts, transaction hashes, the refund reason. `kind` is `in` (into ZEC), `out` (out of ZEC) or `across`. `timeEstimate` is 1Click's estimate from the quote, in seconds. The reply holds no payout or refund address. A 404 means 1Click does not know the address. Treat the proof like a key: send it in the body only, never in a URL. The tracking page takes it after the `#`, which a browser never puts in a request URL, so it stays out of access logs: `https://zecretswap.com/track#.`. A link with no proof shows the status only. ### POST /api/deposit Body: `{ txHash, depositAddress }`. Returns `{ ok: true }`. Optional: 1Click finds the deposit by itself. The hash must fit the chain of the deposit address. ### GET /api/health Returns `{ oneClick: "up" | "down", checkedAt }`. Not cached. HTTP 200 while 1Click has answered in the last two minutes, 503 when it has not. ### Errors A failed call returns `{ error: { code, message, minAmount?, minUsd?, retryAfter?, paused? } }`. Match on `code`, not on `message`. `paused: true` comes with `no-route`: NEAR Intents has paused the pair for now, so try another network or token, not another amount. - `bad-request` (HTTP 400, 403, 404, 413, 415): The request is wrong, the origin is another site, or the deposit address is unknown. Fix it. - `below-min` (HTTP 400): The amount is below the minimum for this pair. `minAmount` (base units) or `minUsd` says how much. - `drift` (HTTP 409): The price moved between two quotes asked for together. Nothing was quoted. Ask again. - `invalid-recipient` (HTTP 400): The payout address is refused for its chain. - `invalid-refund` (HTTP 400): The refund address is refused for its chain. A ZEC refund needs a transparent address (t1…). - `no-route` (HTTP 400): There is no route for this pair right now. Try another amount or another token. With `paused: true`, NEAR Intents has paused the pair: try another network or token. - `no-confidential-route` (HTTP 400, 502): There is no confidential quote. The server never falls back to a public one. Nothing was quoted. - `rate-limited` (HTTP 429): Too many calls. `retryAfter` and the Retry-After header say how many seconds to wait. - `unreachable` (HTTP 502): 1Click did not answer. Try again. - `upstream` (HTTP 502): 1Click is unavailable. Try again. ## Check every live quote before you send The signature proves that 1Click produced the quote. It does not prove that the quote is the swap you asked for. A server between you and 1Click could change the address. So check all of these on the live quote. If any one fails, send nothing. 1. The signature holds. It is ed25519, by ed25519:reYaWhvwu8Jzo3WUM3zhn6VrhuMEF4eADL17qtRVifc. See "The signature" for what it covers. 2. The route is confidential: `route` is `basic` or `advanced`, and `quote.quoteRequest.confidentiality` says the same. Neither is signed, so each is a claim. Agreement between them is the most a client can check. 3. The signed request is your swap: `dry` is false, `swapType` is EXACT_INPUT, `depositType` and `refundType` are ORIGIN_CHAIN, `recipientType` is DESTINATION_CHAIN, `originAsset` and `destinationAsset` are the two you chose and differ, `recipient` and `refundTo` are the two addresses you sent, and `amount` and `quote.quote.amountIn` are exactly the amount you asked for, in base units. 4. The deposit address fits the origin chain, and nothing else is asked of you: there is no `depositMemo`, no `virtualChainRecipient`, no `virtualChainRefundRecipient` and no `customRecipientMsg`, and `depositMode` is absent or SIMPLE. 5. `slippageTolerance` is the slippage you chose. 6. The fees in `appFees` add up to 60 basis points or fewer, and not below zero. The signature does not cover them. 7. `minAmountIn` is above zero and no more than `amountIn`. `minAmountOut` is above zero, no more than `amountOut`, and not below `amountOut` times (10000 minus the slippage) over 10000, less one unit. For a payout on Hyperliquid, 1Click takes the slippage before its payout fee: there, add `withdrawFee` (counted up to `amountOut`) to `amountOut` and to `minAmountOut` before you compare. 8. `amountInFormatted` and `amountOutFormatted` are the base-unit amounts with each token's decimals applied. 9. The signed dollar figures bound the swap: `amountInUsd` is no more than 50,000 dollars plus 2%, and `amountInUsd` less `amountOutUsd` less the payout network fee is no more than 3% of `amountInUsd`. 10. `timestamp` is within 5 minutes of your clock. 11. `quoteRequest.deadline` is at least 10 minutes, plus a margin for the chain, and at most 24 hours after `timestamp`. `quote.deadline` is no earlier than that, and within 14 days of `timestamp`. ### The signature The key is ed25519:reYaWhvwu8Jzo3WUM3zhn6VrhuMEF4eADL17qtRVifc. It is 1Click's. The message is the base58 text of the SHA-256 of one JSON string. The JSON is a single flat object with its keys sorted, no spaces, and no field that is undefined. It holds these request fields: dry, swapType, slippageTolerance, originAsset, depositType, destinationAsset, amount, refundTo, refundType, recipient, recipientType, deadline, and, only when they are set and not zero, quoteWaitingTimeMs, referral, virtualChainRecipient, virtualChainRefundRecipient, customRecipientMsg. It holds these quote fields: amountIn, amountInFormatted, amountInUsd, minAmountIn, amountOut, amountOutFormatted, amountOutUsd, minAmountOut, and for a live quote, when they are set, depositAddress, depositMemo, deadline, timeWhenInactive, timeEstimate, refundFee, withdrawFee. It holds `timestamp`. Check the ed25519 signature, base58 after the `ed25519:` prefix, over the UTF-8 bytes of that base58 text, with the key above. The CLI's source is the reference: packages/cli, with the repo's src/lib/oneclick/signature.ts. ## Rules - Check the signature before you send. 1Click, NEAR Intents' swap service, signs every quote. Check its signature. Check that the signed request is the swap you asked for. The CLI does both. Do not send funds on a quote you have not checked. - Send exactly what the quote says. Send the quoted amount of the quoted token on the quoted chain. Send it in one transfer, from your own wallet. - Give a refund address you control. If the swap can't finish, NEAR Intents sends your deposit back here, minus a refund fee. Use the wallet you send from, or another you control, not an exchange. When you pay with ZEC, use a t1… address: NEAR Intents refunds ZEC to a transparent address only, and a refund there is public. - Use a new payout address each time. Your wallet can make as many as you like. The CLI keeps no list of addresses, so this check is yours. - NEAR Intents screens every swap. It can delay or freeze funds. - Read the fee. Zecret Swap charges 0.4%. NEAR Intents charges its own fee, about 0.2% (less on stablecoin pairs). The quote lists both. - Stay inside the limits. Each swap is $5 to $50,000. Each minute, one IP address may ask for 40 dry quotes, 8 live quotes, 90 status reads and 12 deposit notices. A busy answer says when to try again. - A wrong chain or a wrong token may not be recoverable. Send exactly what the quote shows. ## Fees and limits Zecret Swap charges 0.4% of each swap (40 basis points). NEAR Intents charges its own fee, about 0.2% (less on stablecoin pairs). Both are in `quoteRequest.appFees`, where our entry's recipient reads `zecret-swap`. The fees and the price difference together are in the signed dollar figures: `amountInUsd` less `amountOutUsd`. A Double hop's second swap pays both fees again. The quote shows the time too: `timeEstimate`, in seconds, counted from the moment the deposit confirms. Once a deposit confirms, a swap takes seconds on fast chains, 8 to 13 minutes for Bitcoin, and up to 30 minutes from other slow chains. Each swap is $5 to $50,000. A pair may have a higher minimum: the error `below-min` says what it is. Rate limits, per IP address, each minute: 40 dry quotes, 8 live quotes, 90 status reads, 12 deposit notices. Past a limit the answer is 429 with `retryAfter` and a Retry-After header. A health read past 30 a minute still answers, with the last check's verdict. ## Who can still read what The NEAR Intents Explorer lists a confidential swap as two separate rows. Each row leaves out one side. - Your deposit and your payout: Public on their own chains. - NEAR's private chain: A small set of operators runs it and can see the swap. - NEAR Intents: Screens every swap and can delay or freeze funds. - Zecret Swap's server: Sees your IP address and the addresses in a quote, and stores none of them. Our host, Cloudflare, keeps a sample of requests, with IP addresses, for up to 31 days. NEAR Intents sees the addresses, not your IP address. Blockchain data providers see the deposit address while you wait, not your IP address. - Direct: A watcher can still pair the deposit and the payout by amount and time. - Double hop: The payout into your wallet shows its address and amount. Transfers after that stay hidden. Matching amounts and timing can still tie the swap in to the swap out, so wait, and swap out a different amount. What a watcher can still match: Amount and time. On a fast chain a direct swap pays out in under a minute after the deposit confirms, for the deposit less the fees and the price difference. An agent can run Direct or a Double hop, one swap at a time. A Double hop is two swaps: first into ZEC at your own shielded address, then out to a new wallet. The website also offers Through Zcash: two swaps from one deposit, with our fee once and NEAR Intents' fee on each swap. The ZEC between them is public, so it adds no privacy over Direct. It is on the website only: these docs and the CLI do not cover it. ## The CLI and the MCP server The CLI is `zecret` (install: `npm install -g zecret`). It runs the same checks as the website's, from the same source, and it never signs or sends. - `zecret tokens [--search q]`: the registry. - `zecret quote --from --to --amount [--slippage bps]`: a dry quote. A token is `symbol:chain` (usdc:base), a chain's own coin (zec, btc, eth, sol) or an asset id. The amount is a decimal in token units. - `zecret swap --from --to --amount --payout
--refund
[--yes]`: checks both addresses for their chains, reads a preview, then asks for the live quote, runs every check above, and prints the deposit address, the exact amount and a payment link. With `--json`, no prompt: pass `--yes`. - `zecret status [--proof ] [--watch]`: the status, or follow it to its end. `zecret swap --json` prints the `proof` and a ready `status` line (`next.status`). With the proof, the reply holds the swap's details too. Without it, the status only. - `zecret deposit `: tell 1Click about the deposit. - `zecret mcp`: an MCP server on stdio with four tools: `tokens`, `quote`, `swap_prepare` (the checked deposit instructions) and `status`. Every command takes `--json` (one JSON document on stdout, errors too) and `--base ` (default https://zecretswap.com). Exit codes: - 0: Done. For `status --watch`: the swap ended with SUCCESS. - 1: A bug in the tool. - 2: A flag, token, amount or address is wrong. Nothing was sent to the service. - 3: The service said no: no route, below the minimum, a bad request. - 4: The service is unreachable, busy or rate limiting. Try again later. - 5: A check failed. The quote is not the swap you asked for. Do not send funds. - 6: Not confirmed: the person said no, there was no --yes, or the price moved past the slippage. - 7: `status --watch`: the swap ended REFUNDED. - 8: `status --watch`: the swap ended FAILED. - 9: `status --watch`: out of time. The swap may still finish. MCP client config: ```json { "mcpServers": { "zecret": { "command": "npx", "args": [ "-y", "zecret", "mcp" ] } } } ``` ## Questions people ask The home page's questions, word for word. ### What makes Zecret Swap unique? You don't have to trust us. Zecret Swap never holds your funds and runs no contracts, admin keys or relayers. Your browser checks NEAR Intents' signature on each quote, and the swap runs on-chain. Our fee is 0.4%. Even with NEAR Intents' fee added, it is the lowest total we measured in October 2026. ### Who developed Zecret Swap? Zecret Swap was developed by Zecret Labs, which also runs it. ### Who holds my funds during a swap? You do, until you send. Then NEAR Intents holds the deposit until it pays out or refunds. Zecret Swap never holds your funds or your keys. ### Which parts of a route provide privacy? NEAR's public record lists a confidential swap as two rows, and no field links them. A small set of operators runs NEAR's private chain and can see the swap. A Double hop adds your own shielded Zcash wallet. The payout into it shows its address and amount. What you do with it after that stays hidden. The longer you wait before you swap out, the harder it is to link the two swaps. ### Does every swap go through Zcash? No. Direct is one confidential swap on NEAR Intents, into any token, ZEC too. Double hop is one swap into your own shielded ZEC, then a second swap that you make when you choose. You pick the route on the swap page. ### How do I swap to shielded ZEC? On the swap page (https://zecretswap.com/swap), pick the token you pay, choose ZEC as the token you get, and give a Unified Address that starts with u1. NEAR Intents pays the ZEC to your shielded wallet. Our guide to shielded ZEC (https://zecretswap.com/guides/swap-to-shielded-zec) has every step. ### Can I send or receive crypto privately? Yes. The Send page (https://zecretswap.com/send) sends a token to someone else, and your wallet never pays theirs. The Receive page (https://zecretswap.com/receive) makes a payment link that anyone can pay with any token, and you get shielded ZEC. ### What can remain visible on public chains? Public-chain steps can reveal addresses, amounts, timing, and other transaction data. Our privacy policy (https://zecretswap.com/privacy) lists what our server, our host and NEAR Intents see. ### Do I need an account or a wallet connection? No. There is no account, and Zecret Swap does not connect to your wallet. It never asks for a seed phrase or private key. You send from any wallet, and your browser checks the quote first. ### How do fees, amounts, and timing work? Zecret Swap charges 0.4% of each swap, and NEAR Intents about 0.2% (less on stablecoin pairs). On Through Zcash, we charge our fee once for both swaps. The quote shows every fee before you send. A Double hop's second swap pays both fees again. A swap is $5 to $50,000. Once a deposit confirms, a swap takes seconds on fast chains, 8 to 13 minutes for Bitcoin, and up to 30 minutes from other slow chains. ### How does Zecret Swap make money? From its fee: 0.4% of each swap. On Through Zcash, it charges the fee once for both swaps. ### What if a swap is late, or refunded? The tracking link from the swap page shows what NEAR Intents reports. A shielded wallet shows ZEC once it syncs. If a fee left the deposit short, the page says so: send only what is missing. A late deposit, or a swap that cannot finish, is refunded to your refund address, minus a refund fee. Need help? Message Support (https://t.me/ZecretLabs). Share your tracking link only in private. ### Can an AI agent use Zecret Swap? Yes. A command-line tool, an MCP server (https://zecretswap.com/agents) and a plain HTTP API give an agent the same quotes and checks. Through Zcash is on the website only. You approve each swap and send from your own wallet. ## Pages - [Home](https://zecretswap.com/): The cheapest private swap we've measured, with a 0.4% fee. Swap any token on a confidential NEAR Intents route, with no account, from $5 to $50,000. - [Swap](https://zecretswap.com/swap): Swap any token privately. Pick two tokens, an amount and a payout address. Your browser checks the quote before it shows where to send. - [Send](https://zecretswap.com/send): Send a token to someone else through NEAR Intents' confidential route. Your wallet never pays theirs. Your browser checks the quote before it shows where to send. - [Receive](https://zecretswap.com/receive): Get paid privately in shielded ZEC. Make a payment link, and anyone can pay it with any token. Zecret Swap can't read your link. - [Guide: how to swap to shielded ZEC](https://zecretswap.com/guides/swap-to-shielded-zec): Swap any token to shielded Zcash in one transfer, with no account. Give a u1 address, and NEAR Intents pays the ZEC to your shielded wallet. - [For agents](https://zecretswap.com/agents): Quote, check and track a private swap from a CLI, an MCP client or plain HTTP. Zecret Swap holds no funds and no keys. - [Partners](https://zecretswap.com/partners): Let your holders buy your token privately. 10% of our fee on their swaps buys your token. - [Terms of Service](https://zecretswap.com/terms): Zecret Swap's terms of service: what the service is, its fees, refunds, the limits of its privacy, and who may use it. - [Privacy Policy](https://zecretswap.com/privacy): Zecret Swap's privacy policy. We keep as little about you as we can, and we never sell it. ## Links - [OpenAPI 3.1](https://zecretswap.com/api/openapi.json): every endpoint, with its request and its reply. - [For agents](https://zecretswap.com/agents): this page's twin, for people. - [Swap](https://zecretswap.com/swap): the website's swap page. - [Track a swap](https://zecretswap.com/track): follow a swap by its deposit address. A link with the proof, `/track#.`, shows its details too. - [1Click docs](https://docs.near-intents.org/integration/distribution-channels/1click-api/quickstart/making-a-request): NEAR Intents' own API documentation. - [Confidential Intents](https://docs.near-intents.org/integration/market-makers/confidential-intents): how the confidential route works. Not affiliated with Zcash, Electric Coin Co., the Zcash Foundation or NEAR. Not financial advice.