Integrating with Deneb
This page is for teams that build on Minter (wallets, Telegram bots and Mini Apps, games, websites) and want to connect to Deneb: the explorer at https://denebnav.app and the DEX at https://dex.denebnav.app. It lists every way to integrate, what each one needs on your side and its honest status.
Status labels:
Works now - live on
dex.denebnav.app, you can use it today.Open for registration - the Deneb side works; you register your product in the developer cabinet and it appears on the DEX after moderation.
In progress - the contract is written, the Deneb side is being built.
Planned - agreed direction, no contract yet.
Which way fits you
| Who you are | Way | Status |
|---|---|---|
| Website, game, bot or channel that wants to send users to a swap | 1. Swap link | Works now |
| Telegram Mini App or bot that holds Minter keys (no WalletConnect) | 2. Link signing | Open for registration |
| Wallet that supports WalletConnect v2 | 3. WalletConnect, minter:1 | Planned |
| App that wants prices or swaps inside its own interface | 4. Prices and swap routes API | Planned |
A Telegram Mini App is a web page, so the same Mini App can also connect over WalletConnect (way 3) once that is available. Link signing is the way for it now.
You can combine ways: for example, a wallet bot can put swap links in its messages today and add link signing next.
1. Swap link ("Swap on Deneb")
Status: works now.
A plain link to the DEX with the pair and, optionally, the amount filled in. No SDK, no API key, no embedding.
https://dex.denebnav.app/swap?from=BIP&to=HUB&amount=100The user lands on the swap screen, sees a fresh quote from Deneb's own node, connects a wallet on the DEX and decides. The link never trades by itself: it only fills in the form.
| Parameter | Meaning | Example |
|---|---|---|
from | Coin the user sells: coin id or ticker | 0, BIP, HUB |
to | Coin the user buys: coin id or ticker | 1902, USDTBSC |
amount | Amount of from to sell, decimal with a dot, at most 18 fraction digits | 100, 12.5 |
amt | The same amount in pip (1 coin = 10^18 pip), integer; wins over amount | 12500000000000000000 |
All parameters are optional. Without them the DEX opens its default pair, BIP to USDTBSC.
Tickers are case-insensitive. A value of digits only is a coin id (
0is BIP). Ids never change, a ticker names whichever coin holds it now, so prefer ids in long-lived links.Only coins that have a pool can be traded.
Anything invalid (unknown coin, malformed amount, value longer than 64 characters) is ignored silently and that side falls back to the default pair. The user never sees an error page.
In the regular (non-PRO) view the swap card trades one coin against BIP, so the amount is kept only when BIP is one side of the pair.
Prices, routes and minimum amounts cannot be passed in the link.
Open the link in a new tab or the system browser. The DEX refuses to be shown in an
<iframe>.Use only
https://dex.denebnav.app/swapas the entry point.
What you do: build the link with URLSearchParams (or your language's equivalent) and put it behind a button.
const url = new URL('https://dex.denebnav.app/swap');
url.search = new URLSearchParams({ from: 'BIP', to: 'HUB', amount: '100' }).toString();Full reference with more examples and a button snippet: swap-link.md.
2. Link signing (wallets without WalletConnect)
Status: open for registration. The Deneb signing service works: https://dex.denebnav.app/api/sign/v1 is live in production. Register your wallet in the developer cabinet (see How to get access); it appears under "Other wallets" on the DEX after a Deneb moderator publishes it. The picker is switched on for users after the first wallet passes moderation. The protocol is still a draft, not frozen: fields are only added, never change meaning, and the places that may change are marked [draft] in connect.md, §9.
For wallets that have no WalletConnect: Telegram Mini Apps, Telegram bots, mobile apps with deep links. The DEX keeps a short-lived request on its server and passes your wallet only an opaque id in a link. Your wallet fetches the request from a fixed Deneb address, shows it, signs with its own key and nonce, broadcasts and reports the hash back. The transaction itself is never in the link, and the key never leaves your wallet.
Flow.
The user picks a swap on the DEX and chooses your wallet under "Other wallets".
The DEX opens your link with the request id, for a Mini App
https://t.me/<bot>?startapp=deneb_<id>(or?start=deneb_<id>for a bot). Your Mini App receives the id instart_param.Your wallet calls
POST /requests/{id}/claimand gets the request (envelope) and a one-timeclaimToken.Your wallet checks it, shows the swap, the user confirms, your wallet signs and broadcasts.
Your wallet calls
POST /requests/{id}/resultwith the hash and the signing address.The DEX finds the transaction in a block through its own node. Only that counts as success.
Base URL (hard-code it, never take it from a link or a request):
https://dex.denebnav.app/api/sign/v1Endpoints for wallets.
| Method and path | Auth | Purpose |
|---|---|---|
POST /requests/{id}/claim | - | Get the request. Works once. |
POST /requests/{id}/result | Bearer <claimToken> (session requests: <walletToken>) | Report sent with hash, rejected with reason, or approved. Accepted once. |
GET /sessions/{sid}/next?wait=25 | Bearer <walletToken> | Long poll for the next session request. |
POST /sessions/{sid}/revoke | Bearer <walletToken> | Courtesy notice that the user revoked a session. |
GET /wallets/disabled | - | Wallets the DEX has switched off. |
What is carried. Only swaps: types 2, 3, 4, 23, 24, 25 per transaction. Send, Multisend, checks and every other type are never carried, and your wallet must refuse them even if the server returns them.
Two modes.
Per transaction (default): the user confirms every request in your wallet.
Session permission (optional, format final, not enabled on the DEX yet): the user grants once a set of limits (pool swaps 23, 24, 25 only, listed coins, caps per trade and in total, max slippage, transaction count, up to 24 h). Your wallet stores and enforces the limits next to the key; nothing on the DEX side can widen them.
What your wallet must check (short form of the checklist in §9.10):
Take only the id from a link, matching
^deneb_(tx|cn|ss|sn)_[A-Za-z0-9_-]{22}$; ignore anything else.Show the service name from your own configuration; refuse if
sourcein the envelope is not the host of the base URL.Check that
chainIdequals your wallet's network (production:"minter:1"only, otherwise refuse withwrong_source; never sign with another chain id), the id, the kind andexpiresAtby your own clock.Never sign the same id twice.
Parse the transaction strictly: allowed types only, no
payload, nodescription, no unknown keys, amounts as pip strings, coin symbols from your own node. Show no text from the request except numbers and addresses.Set nonce, gas price and chain id yourself and broadcast yourself.
Get your own quote from your own node, show "you receive at least X", warn on a big deviation and refuse a zero minimum.
Ask the user every time; a request that came via a link is never signed without a prompt.
Keep
claimTokenandwalletTokenin memory or secure storage, never in logs.
Full contract: connect.md, §9 Link signing (in English): envelope fields, limits, errors, delivery of session requests for bots and Mini Apps, and what the DEX checks.
3. WalletConnect, namespace minter:1
Status: planned. The contract is a draft and may change until it is frozen.
For wallets that support WalletConnect v2 (Sign API). The DEX proposes a session, the wallet approves it with one account, then the DEX sends minter_sendTransaction requests that the wallet shows, signs and broadcasts.
| Item | Value |
|---|---|
| Namespace | minter |
| Mainnet | minter:1 |
| Testnet | minter:2 |
| Account (CAIP-10) | minter:1:Mx + 40 lowercase hex characters |
| Method | minter_sendTransaction |
| Events | accountsChanged, chainChanged |
The chain reference is the chainId inside the signed Minter transaction; the wallet must check that they match. Request format, transaction types, events, checks after the answer and errors: connect.md, §1-8. These sections are currently in Russian.
4. Prices and swap routes API
Status: planned. No public endpoints yet, so there is nothing to call today.
For projects that want to show prices or build swaps inside their own interface instead of sending users to the DEX. If this is what you need, tell us which coins and pairs, whether you need prices only or full routes ready to sign, and how often you would ask. Until then, the swap link (way 1) is the way to hand a swap to Deneb.
How to get access
The swap link (way 1) needs no access: build the link and use it.
Register your wallet in the developer cabinet
Link signing (way 2) is set up by you, in the developer cabinet at https://developers.denebnav.app: Integrations → Add → Wallet. There is no list to send us and nothing to change on the Deneb side. Status: open for registration - the cabinet section works; you can register a wallet now.
Sign in and turn on a passkey for your account (required for accounts that own a wallet).
Create the wallet: name, icon (PNG or JPEG, we store and serve it), website, emergency contact.
Add connect methods: Telegram Mini App
https://t.me/<bot>/<app>?startapp=deneb_{id}, Telegram bothttps://t.me/<bot>?startapp=deneb_{id}or?start=deneb_{id}, a link on your own verified domain, and a marker if you also support WalletConnectminter:1. Onlyhttps://, a single{id}, no custom URL schemes. On desktop the DEX shows your link as a QR code.Prove ownership: a token from the cabinet in your bot's short description, or in
https://<host>/.well-known/deneb-wallet.jsonon your domain.Press Send test request: a testnet request your wallet claims and answers. No real money, never on mainnet.
Press Submit for review. A Deneb moderator publishes it once; DEX users then see it under Other wallets, marked as a third-party wallet. The "Other wallets" picker is not switched on for users yet: it is enabled after the first wallet passes moderation.
After publication you edit the name, icon and website freely. Changes to connect methods or the emergency contact go back to review, and the published version keeps working until they are approved. You can disable your wallet at any time, and so can Deneb; ownership is re-checked every 24 hours and a wallet whose bot or domain changed hands is disabled automatically.
Full rules: connect.md, §9.12 Registering your wallet.
Cabinet API behind the Wallets section
The Integrations section of the cabinet (the wallet form) uses these endpoints on the cabinet origin (https://developers.denebnav.app), with the cabinet session cookie. Writes are POST or PUT with a JSON body and the exact cabinet Origin. Errors are {"error": "<code>", "message": "…"}. Each answer with a wallet is {"wallet": {...}}: id, status (draft, review, rejected, published, disabled), disabled (who, when, reason, whether enabling was requested), and two versions, published (live) and pending (the draft, or the version in review or rejected), each with number, status, hash, name, icon_url, website, contact (email, verified), methods, review_comment.
| Endpoint | What it does | ||
|---|---|---|---|
GET /api/account/wallets | Your wallets (at most 3 per account). | ||
POST /api/account/wallets {"name","website","contact","methods"} | Creates a wallet with a draft. Fields may be empty; filled fields are checked against the rules above. | ||
GET /api/account/wallets/{id} | One wallet. | ||
PUT /api/account/wallets/{id} {"name","website","contact","methods"} | Replaces the draft (the icon stays). After publication this is a new version; the published one keeps working. Not while in review. | ||
POST /api/account/wallets/{id}/icon {"image":"<base64>"} | Uploads the icon (PNG or JPEG, up to 512 KB) into the draft; it is re-encoded to a 256×256 PNG. | ||
GET /api/account/wallets/icons/{sha256}.png | Your icon, served as an inert PNG. | ||
POST /api/account/wallets/{id}/submit | Sends the draft to review. Needs a recent sign-in (10 minutes) until passkeys arrive. | ||
POST /api/account/wallets/{id}/withdraw | Takes the version in review back to a draft. | ||
POST /api/account/wallets/{id}/disable | Disables your published wallet at once. | ||
POST /api/account/wallets/{id}/enable | Asks to enable it again after you disabled it. Until passkeys and ownership checks arrive, a Deneb moderator does it. | ||
POST /api/account/wallets/{id}/contact | Emails a confirmation link to the emergency contact of the draft. The link works once, for 24 hours; a new one replaces it. | ||
POST /api/account/wallets/contact/verify {"token"} | Used by the page the link opens (no sign-in needed): confirms the contact. | ||
POST /api/account/wallets/{id}/ownership-token {"target":"<host or bot>"} | Issues a 24-hour proof token for a host (your domain) or a Telegram bot. Returns {"token","kind","target","expires_at"}; the token is in this answer only. Put it in https://<host>/.well-known/deneb-wallet.json ({"tokens":["<token>"]}) or in your bot's short description. | ||
POST /api/account/wallets/{id}/ownership-verify {"target":"<host or bot>"} | Reads the token back from the target and returns `{"result":"verified" | "not_found" | "unreadable"}. verified proves the target until a check finds the token gone (not_found); unreadable` changes nothing. Keep the token in place. A bot needs a short description to be checked. |
A method is {"kind", "template", "modes", "delivery"}: kind is telegram_bot, telegram_app, domain or walletconnect (a marker, no other fields); modes are tx and/or session; delivery (bot or mini_app) is required with session. There is no publish endpoint: only a Deneb moderator publishes.
For WalletConnect and the prices API (ways 3 and 4), contact the Deneb team for now. Self-service API keys in the cabinet are planned.
What to tell us about your wallet:
Where is the user's key kept: on your server (bot) or on the user's device (Mini App, app)? Who can sign with it?
Does your wallet support WalletConnect v2 today?
Which wrapped tokens do you use (tickers and coin ids on Minter), and which pools should be tradable for your users?